14bff34e3Sthurlow /*
24bff34e3Sthurlow  * CDDL HEADER START
34bff34e3Sthurlow  *
44bff34e3Sthurlow  * The contents of this file are subject to the terms of the
54bff34e3Sthurlow  * Common Development and Distribution License (the "License").
64bff34e3Sthurlow  * You may not use this file except in compliance with the License.
74bff34e3Sthurlow  *
84bff34e3Sthurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94bff34e3Sthurlow  * or http://www.opensolaris.org/os/licensing.
104bff34e3Sthurlow  * See the License for the specific language governing permissions
114bff34e3Sthurlow  * and limitations under the License.
124bff34e3Sthurlow  *
134bff34e3Sthurlow  * When distributing Covered Code, include this CDDL HEADER in each
144bff34e3Sthurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154bff34e3Sthurlow  * If applicable, add the following below this CDDL HEADER, with the
164bff34e3Sthurlow  * fields enclosed by brackets "[]" replaced with your own identifying
174bff34e3Sthurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
184bff34e3Sthurlow  *
194bff34e3Sthurlow  * CDDL HEADER END
204bff34e3Sthurlow  */
214bff34e3Sthurlow 
224bff34e3Sthurlow /*
234bff34e3Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
244bff34e3Sthurlow  * Use is subject to license terms.
25*adee6784SGordon Ross  *
26*adee6784SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
274bff34e3Sthurlow  */
284bff34e3Sthurlow 
294bff34e3Sthurlow /*
304bff34e3Sthurlow  * SMB specific functions
314bff34e3Sthurlow  */
324bff34e3Sthurlow #include <stdio.h>
334bff34e3Sthurlow #include <string.h>
344bff34e3Sthurlow #include <ctype.h>
354bff34e3Sthurlow #include <stdlib.h>
364bff34e3Sthurlow #include <unistd.h>
374bff34e3Sthurlow #include <zone.h>
384bff34e3Sthurlow #include <errno.h>
394bff34e3Sthurlow #include <locale.h>
404bff34e3Sthurlow #include <signal.h>
414bff34e3Sthurlow #include <fcntl.h>
424bff34e3Sthurlow #include <sys/types.h>
434bff34e3Sthurlow #include <sys/stat.h>
444bff34e3Sthurlow #include <syslog.h>
454bff34e3Sthurlow #include "libshare.h"
464bff34e3Sthurlow #include "libshare_impl.h"
474bff34e3Sthurlow #include <pwd.h>
484bff34e3Sthurlow #include <limits.h>
494bff34e3Sthurlow #include <libscf.h>
504bff34e3Sthurlow #include <strings.h>
514bff34e3Sthurlow #include "libshare_smbfs.h"
524bff34e3Sthurlow #include <rpcsvc/daemon_utils.h>
534bff34e3Sthurlow #include <arpa/inet.h>
544bff34e3Sthurlow #include <uuid/uuid.h>
554bff34e3Sthurlow #include <netsmb/smb_lib.h>
564bff34e3Sthurlow 
574bff34e3Sthurlow #define	SMBFS_PROTOCOL_NAME	"smbfs"
584bff34e3Sthurlow 
594bff34e3Sthurlow /* internal functions */
604bff34e3Sthurlow static uint64_t smbfs_features();
614bff34e3Sthurlow static int smbfs_init();
624bff34e3Sthurlow static void smbfs_fini();
634bff34e3Sthurlow static int smbfs_set_proto_prop(sa_property_t);
644bff34e3Sthurlow static sa_protocol_properties_t smbfs_get_proto_set();
654bff34e3Sthurlow static char *smbfs_get_status();
664bff34e3Sthurlow static int smbfs_delete_section(char *);
674bff34e3Sthurlow static int smbfs_delete_property_group(char *);
684bff34e3Sthurlow 
694bff34e3Sthurlow static int range_check_validator(int, char *, char *);
704bff34e3Sthurlow static int string_length_check_validator(int, char *, char *);
714bff34e3Sthurlow static int yes_no_validator(int, char *, char *);
724bff34e3Sthurlow static int ip_address_validator(int, char *, char *);
734bff34e3Sthurlow static int minauth_validator(int, char *, char *);
744bff34e3Sthurlow static int password_validator(int, char *, char *);
75*adee6784SGordon Ross static int protocol_validator(int, char *, char *);
769c9af259SGordon Ross static int signing_validator(int, char *, char *);
774bff34e3Sthurlow 
784bff34e3Sthurlow int propset_changed = 0;
794bff34e3Sthurlow 
804bff34e3Sthurlow /*
814bff34e3Sthurlow  * ops vector that provides the protocol specific info and operations
824bff34e3Sthurlow  * for share management.
834bff34e3Sthurlow  */
844bff34e3Sthurlow 
854bff34e3Sthurlow struct sa_plugin_ops sa_plugin_ops = {
864bff34e3Sthurlow 	SA_PLUGIN_VERSION,
874bff34e3Sthurlow 	SMBFS_PROTOCOL_NAME,
884bff34e3Sthurlow 	smbfs_init,
894bff34e3Sthurlow 	smbfs_fini,
904bff34e3Sthurlow 	NULL,	/* share */
914bff34e3Sthurlow 	NULL,	/* unshare */
924bff34e3Sthurlow 	NULL,	/* valid_prop */
934bff34e3Sthurlow 	NULL,	/* valid_space */
944bff34e3Sthurlow 	NULL,	/* security_prop */
954bff34e3Sthurlow 	NULL,	/* legacy_opts */
964bff34e3Sthurlow 	NULL,	/* legacy_format */
974bff34e3Sthurlow 	smbfs_set_proto_prop,
984bff34e3Sthurlow 	smbfs_get_proto_set,
994bff34e3Sthurlow 	smbfs_get_status,
1004bff34e3Sthurlow 	NULL,	/* space_alias */
1014bff34e3Sthurlow 	NULL,	/* update_legacy */
1024bff34e3Sthurlow 	NULL,	/* delete_legacy */
1034bff34e3Sthurlow 	NULL,	/* change_notify */
1044bff34e3Sthurlow 	NULL,	/* enable_resource */
1054bff34e3Sthurlow 	NULL,	/* disable_resource */
1064bff34e3Sthurlow 	smbfs_features,
1074bff34e3Sthurlow 	NULL,	/* get_transient_shares */
1084bff34e3Sthurlow 	NULL,	/* notify_resource */
1094bff34e3Sthurlow 	NULL,	/* rename_resource */
1104bff34e3Sthurlow 	NULL,	/* run_command */
1114bff34e3Sthurlow 	NULL,	/* command_help */
1124bff34e3Sthurlow 	smbfs_delete_section,
1134bff34e3Sthurlow };
1144bff34e3Sthurlow 
1154bff34e3Sthurlow /*
1164bff34e3Sthurlow  * is_a_number(number)
1174bff34e3Sthurlow  *
1184bff34e3Sthurlow  * is the string a number in one of the forms we want to use?
1194bff34e3Sthurlow  */
1204bff34e3Sthurlow 
1214bff34e3Sthurlow static int
is_a_number(char * number)1224bff34e3Sthurlow is_a_number(char *number)
1234bff34e3Sthurlow {
1244bff34e3Sthurlow 	int ret = 1;
1254bff34e3Sthurlow 	int hex = 0;
1264bff34e3Sthurlow 
1274bff34e3Sthurlow 	if (strncmp(number, "0x", 2) == 0) {
1284bff34e3Sthurlow 		number += 2;
1294bff34e3Sthurlow 		hex = 1;
1304bff34e3Sthurlow 	} else if (*number == '-') {
1314bff34e3Sthurlow 		number++; /* skip the minus */
1324bff34e3Sthurlow 	}
1334bff34e3Sthurlow 
1344bff34e3Sthurlow 	while (ret == 1 && *number != '\0') {
1354bff34e3Sthurlow 		if (hex) {
1364bff34e3Sthurlow 			ret = isxdigit(*number++);
1374bff34e3Sthurlow 		} else {
1384bff34e3Sthurlow 			ret = isdigit(*number++);
1394bff34e3Sthurlow 		}
1404bff34e3Sthurlow 	}
1414bff34e3Sthurlow 	return (ret);
1424bff34e3Sthurlow }
1434bff34e3Sthurlow 
1444bff34e3Sthurlow /*
1454bff34e3Sthurlow  * Protocol management functions
1464bff34e3Sthurlow  *
1474bff34e3Sthurlow  * properties defined in the default files are defined in
1484bff34e3Sthurlow  * proto_option_defs for parsing and validation.
1494bff34e3Sthurlow  */
1504bff34e3Sthurlow 
1514bff34e3Sthurlow struct smbclnt_proto_option_defs smbclnt_proto_options[] = {
1524bff34e3Sthurlow 	{ "section", NULL, PROTO_OPT_SECTION,
1534bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1544bff34e3Sthurlow 	    string_length_check_validator},
1554bff34e3Sthurlow 	{ "addr", NULL, PROTO_OPT_ADDR,
1564bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1574bff34e3Sthurlow 	    ip_address_validator},
1584bff34e3Sthurlow 	{ "minauth", NULL, PROTO_OPT_MINAUTH,
1594bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1604bff34e3Sthurlow 	    minauth_validator},
1614bff34e3Sthurlow 	{ "nbns_broadcast", NULL, PROTO_OPT_NBNS_BROADCAST,
1624bff34e3Sthurlow 	    0, 0, 0,
1634bff34e3Sthurlow 	    yes_no_validator},
1644bff34e3Sthurlow 	{ "nbns_enable", NULL, PROTO_OPT_NBNS_ENABLE,
1654bff34e3Sthurlow 	    0, 0, 0,
1664bff34e3Sthurlow 	    yes_no_validator},
1674bff34e3Sthurlow 	{ "nbns", NULL, PROTO_OPT_NBNSADDR,
1684bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1694bff34e3Sthurlow 	    ip_address_validator},
1704bff34e3Sthurlow 	{ "password", NULL, PROTO_OPT_PASSWORD,
1714bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1724bff34e3Sthurlow 	    password_validator},
1734bff34e3Sthurlow 	{ "timeout", NULL, PROTO_OPT_TIMEOUT,
1744bff34e3Sthurlow 	    0, 0, 60,
1754bff34e3Sthurlow 	    range_check_validator},
1764bff34e3Sthurlow 	{ "user", NULL, PROTO_OPT_USER,
1774bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1784bff34e3Sthurlow 	    string_length_check_validator},
1794bff34e3Sthurlow 	{ "domain", NULL, PROTO_OPT_DOMAIN,
1804bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1814bff34e3Sthurlow 	    string_length_check_validator},
1824bff34e3Sthurlow 	{ "workgroup", NULL, PROTO_OPT_WORKGROUP,
1834bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1844bff34e3Sthurlow 	    string_length_check_validator},
1859c9af259SGordon Ross 	{ "signing", NULL, PROTO_OPT_SIGNING,
1864bff34e3Sthurlow 	    0, 0, MAX_VALUE_BUFLEN,
1879c9af259SGordon Ross 	    signing_validator},
188*adee6784SGordon Ross 	{ "min_protocol", NULL, PROTO_OPT_MIN_PROTOCOL,
189*adee6784SGordon Ross 	    0, 0, MAX_VALUE_BUFLEN,
190*adee6784SGordon Ross 	    protocol_validator},
191*adee6784SGordon Ross 	{ "max_protocol", NULL, PROTO_OPT_MAX_PROTOCOL,
192*adee6784SGordon Ross 	    0, 0, MAX_VALUE_BUFLEN,
193*adee6784SGordon Ross 	    protocol_validator},
1944bff34e3Sthurlow 	{NULL}
1954bff34e3Sthurlow };
1964bff34e3Sthurlow 
1974bff34e3Sthurlow /*
1984bff34e3Sthurlow  * Check the range of value as int range.
1994bff34e3Sthurlow  */
2004bff34e3Sthurlow /*ARGSUSED*/
2014bff34e3Sthurlow static int
range_check_validator(int index,char * section,char * value)2024bff34e3Sthurlow range_check_validator(int index, char *section, char *value)
2034bff34e3Sthurlow {
2044bff34e3Sthurlow 	int ret = SA_OK;
2054bff34e3Sthurlow 
2064bff34e3Sthurlow 	if (value == NULL)
2074bff34e3Sthurlow 		return (SA_BAD_VALUE);
2084bff34e3Sthurlow 	if (strlen(value) == 0)
2094bff34e3Sthurlow 		return (SA_OK);
2104bff34e3Sthurlow 	if (!is_a_number(value)) {
2114bff34e3Sthurlow 		ret = SA_BAD_VALUE;
2124bff34e3Sthurlow 	} else {
2134bff34e3Sthurlow 		int val;
2144bff34e3Sthurlow 		val = strtoul(value, NULL, 0);
2154bff34e3Sthurlow 		if (val < smbclnt_proto_options[index].minval ||
2164bff34e3Sthurlow 		    val > smbclnt_proto_options[index].maxval)
2174bff34e3Sthurlow 			ret = SA_BAD_VALUE;
2184bff34e3Sthurlow 	}
2194bff34e3Sthurlow 	return (ret);
2204bff34e3Sthurlow }
2214bff34e3Sthurlow 
2224bff34e3Sthurlow /*
2234bff34e3Sthurlow  * Check the length of the string
2244bff34e3Sthurlow  */
2254bff34e3Sthurlow /*ARGSUSED*/
2264bff34e3Sthurlow static int
string_length_check_validator(int index,char * section,char * value)2274bff34e3Sthurlow string_length_check_validator(int index, char *section, char *value)
2284bff34e3Sthurlow {
2294bff34e3Sthurlow 	int ret = SA_OK;
2304bff34e3Sthurlow 
2314bff34e3Sthurlow 	if (value == NULL)
2324bff34e3Sthurlow 		return (SA_BAD_VALUE);
2334bff34e3Sthurlow 	if (strlen(value) == 0)
2344bff34e3Sthurlow 		return (SA_OK);
2354bff34e3Sthurlow 	if (strlen(value) > smbclnt_proto_options[index].maxval)
2364bff34e3Sthurlow 		ret = SA_BAD_VALUE;
2374bff34e3Sthurlow 	return (ret);
2384bff34e3Sthurlow }
2394bff34e3Sthurlow 
2404bff34e3Sthurlow /*
2414bff34e3Sthurlow  * Check yes/no
2424bff34e3Sthurlow  */
2434bff34e3Sthurlow /*ARGSUSED*/
2444bff34e3Sthurlow static int
yes_no_validator(int index,char * section,char * value)2454bff34e3Sthurlow yes_no_validator(int index, char *section, char *value)
2464bff34e3Sthurlow {
2474bff34e3Sthurlow 	if (value == NULL)
2484bff34e3Sthurlow 		return (SA_BAD_VALUE);
2494bff34e3Sthurlow 	if (strlen(value) == 0)
2504bff34e3Sthurlow 		return (SA_OK);
2514bff34e3Sthurlow 	if ((strcasecmp(value, "yes") == 0) ||
2524bff34e3Sthurlow 	    (strcasecmp(value, "no") == 0) ||
2534bff34e3Sthurlow 	    (strcasecmp(value, "true") == 0) ||
2544bff34e3Sthurlow 	    (strcasecmp(value, "false") == 0))
2554bff34e3Sthurlow 		return (SA_OK);
2564bff34e3Sthurlow 	return (SA_BAD_VALUE);
2574bff34e3Sthurlow }
2584bff34e3Sthurlow 
2594bff34e3Sthurlow /*
2604bff34e3Sthurlow  * Check IP address.
2614bff34e3Sthurlow  */
2624bff34e3Sthurlow /*ARGSUSED*/
2634bff34e3Sthurlow static int
ip_address_validator(int index,char * section,char * value)2644bff34e3Sthurlow ip_address_validator(int index, char *section, char *value)
2654bff34e3Sthurlow {
2664bff34e3Sthurlow 	int len;
2674bff34e3Sthurlow 
2684bff34e3Sthurlow 	if (value == NULL)
2694bff34e3Sthurlow 		return (SA_BAD_VALUE);
2704bff34e3Sthurlow 	len = strlen(value);
2714bff34e3Sthurlow 	if (len == 0)
2724bff34e3Sthurlow 		return (SA_OK);
2734bff34e3Sthurlow 	if (len > MAX_VALUE_BUFLEN)
2744bff34e3Sthurlow 		return (SA_BAD_VALUE);
2754bff34e3Sthurlow 	return (SA_OK);
2764bff34e3Sthurlow }
2774bff34e3Sthurlow 
2784bff34e3Sthurlow /*ARGSUSED*/
2794bff34e3Sthurlow static int
minauth_validator(int index,char * section,char * value)2804bff34e3Sthurlow minauth_validator(int index, char *section, char *value)
2814bff34e3Sthurlow {
282*adee6784SGordon Ross 	int ival;
283*adee6784SGordon Ross 
2844bff34e3Sthurlow 	if (value == NULL)
2854bff34e3Sthurlow 		return (SA_BAD_VALUE);
286*adee6784SGordon Ross 	ival = smb_cf_minauth_from_str(value);
287*adee6784SGordon Ross 	if (ival == -1)
2884bff34e3Sthurlow 		return (SA_BAD_VALUE);
289*adee6784SGordon Ross 
290*adee6784SGordon Ross 	return (SA_OK);
291*adee6784SGordon Ross }
292*adee6784SGordon Ross 
293*adee6784SGordon Ross /*ARGSUSED*/
294*adee6784SGordon Ross static int
protocol_validator(int index,char * section,char * value)295*adee6784SGordon Ross protocol_validator(int index, char *section, char *value)
296*adee6784SGordon Ross {
297*adee6784SGordon Ross 	int ival;
298*adee6784SGordon Ross 
299*adee6784SGordon Ross 	if (value == NULL)
300*adee6784SGordon Ross 		return (SA_BAD_VALUE);
301*adee6784SGordon Ross 	ival = smb_cf_version_from_str(value);
302*adee6784SGordon Ross 	if (ival == -1)
303*adee6784SGordon Ross 		return (SA_BAD_VALUE);
304*adee6784SGordon Ross 
305*adee6784SGordon Ross 	return (SA_OK);
3064bff34e3Sthurlow }
3074bff34e3Sthurlow 
3084bff34e3Sthurlow /*ARGSUSED*/
3094bff34e3Sthurlow static int
signing_validator(int index,char * section,char * value)3109c9af259SGordon Ross signing_validator(int index, char *section, char *value)
3114bff34e3Sthurlow {
3129c9af259SGordon Ross 	if (value == NULL)
3139c9af259SGordon Ross 		return (SA_BAD_VALUE);
3149c9af259SGordon Ross 	if (strlen(value) == 0)
3159c9af259SGordon Ross 		return (SA_OK);
3169c9af259SGordon Ross 	if (strcmp(value, "disabled") == 0 ||
3179c9af259SGordon Ross 	    strcmp(value, "enabled") == 0 ||
3189c9af259SGordon Ross 	    strcmp(value, "required") == 0)
3199c9af259SGordon Ross 		return (SA_OK);
3209c9af259SGordon Ross 	else
3219c9af259SGordon Ross 		return (SA_BAD_VALUE);
3224bff34e3Sthurlow }
3234bff34e3Sthurlow 
3244bff34e3Sthurlow /*ARGSUSED*/
3254bff34e3Sthurlow static int
password_validator(int index,char * section,char * value)3264bff34e3Sthurlow password_validator(int index, char *section, char *value)
3274bff34e3Sthurlow {
3284bff34e3Sthurlow 	char buffer[100];
3294bff34e3Sthurlow 
3304bff34e3Sthurlow 	/* mangled passwords will start with this pattern */
3314bff34e3Sthurlow 	if (strlen(value) == 0)
3324bff34e3Sthurlow 		return (SA_OK);
3334bff34e3Sthurlow 	if (strncmp(value, "$$1", 3) != 0)
3344bff34e3Sthurlow 		return (SA_PASSWORD_ENC);
3354bff34e3Sthurlow 	if (smb_simpledecrypt(buffer, value) != 0)
3364bff34e3Sthurlow 		return (SA_BAD_VALUE);
3374bff34e3Sthurlow 	return (SA_OK);
3384bff34e3Sthurlow }
3394bff34e3Sthurlow 
3404bff34e3Sthurlow 
3414bff34e3Sthurlow /*
3424bff34e3Sthurlow  * the protoset holds the defined options so we don't have to read
3434bff34e3Sthurlow  * them multiple times
3444bff34e3Sthurlow  */
3454bff34e3Sthurlow sa_protocol_properties_t protoset;
3464bff34e3Sthurlow 
3474bff34e3Sthurlow static int
findprotoopt(char * name)3484bff34e3Sthurlow findprotoopt(char *name)
3494bff34e3Sthurlow {
3504bff34e3Sthurlow 	int i;
3514bff34e3Sthurlow 	for (i = 0; smbclnt_proto_options[i].name != NULL; i++) {
3524bff34e3Sthurlow 		if (strcasecmp(smbclnt_proto_options[i].name, name) == 0)
3534bff34e3Sthurlow 			return (i);
3544bff34e3Sthurlow 	}
3554bff34e3Sthurlow 	return (-1);
3564bff34e3Sthurlow }
3574bff34e3Sthurlow 
3584bff34e3Sthurlow /*
3594bff34e3Sthurlow  * Load the persistent settings from SMF.  Each section is an SMF
3604bff34e3Sthurlow  * property group with an "S-" prefix and a UUID, and the section
3614bff34e3Sthurlow  * is itself a property which can have a more flexible name than
3624bff34e3Sthurlow  * a property group name can have.  The section name need not be
3634bff34e3Sthurlow  * the first property, so we have to be a little flexible, but
3644bff34e3Sthurlow  * the change of name of the property groups is a reliable way
3654bff34e3Sthurlow  * to know that we're seeing a different section.
3664bff34e3Sthurlow  */
3674bff34e3Sthurlow int
smbclnt_config_load()3684bff34e3Sthurlow smbclnt_config_load()
3694bff34e3Sthurlow {
3704bff34e3Sthurlow 	scf_simple_app_props_t *props = NULL;
3714bff34e3Sthurlow 	scf_simple_prop_t *prop = NULL, *lastprop = NULL;
3724bff34e3Sthurlow 	char *lastpgname = NULL, *pgname = NULL;
3734bff34e3Sthurlow 	char *name = NULL, *value = NULL;
3744bff34e3Sthurlow 	sa_property_t sect, node;
3754bff34e3Sthurlow 
3764bff34e3Sthurlow 	props = scf_simple_app_props_get(NULL, SMBC_DEFAULT_INSTANCE_FMRI);
3774bff34e3Sthurlow 	if (props == NULL)
3784bff34e3Sthurlow 		return (-1);
3794bff34e3Sthurlow 
3809c9af259SGordon Ross 	for (;;) {
3819c9af259SGordon Ross 		lastprop = prop;
3829c9af259SGordon Ross 		prop = (scf_simple_prop_t *)
3839c9af259SGordon Ross 		    scf_simple_app_props_next(props, lastprop);
3849c9af259SGordon Ross 		if (prop == NULL)
3859c9af259SGordon Ross 			break;
3864bff34e3Sthurlow 
3874bff34e3Sthurlow 		/* Ignore properties that don't have our prefix */
3884bff34e3Sthurlow 		pgname = scf_simple_prop_pgname(prop);
3899c9af259SGordon Ross 		if (strncmp("S-", pgname, 2) != 0)
3904bff34e3Sthurlow 			continue;
3914bff34e3Sthurlow 
3929c9af259SGordon Ross 		/*
3939c9af259SGordon Ross 		 * Note property group name changes, which mark sections
3949c9af259SGordon Ross 		 *
3959c9af259SGordon Ross 		 * The memory allocated by sa_create_section is
3969c9af259SGordon Ross 		 * linked into the list of children under protoset,
3979c9af259SGordon Ross 		 * and will eventually be freed via that list.
3989c9af259SGordon Ross 		 */
3994bff34e3Sthurlow 		if (lastpgname == NULL || strcmp(lastpgname, pgname) != 0) {
4004bff34e3Sthurlow 			sect = sa_create_section(NULL, pgname+2);
4014bff34e3Sthurlow 			(void) xmlSetProp(sect, (xmlChar *)"type",
4024bff34e3Sthurlow 			    (xmlChar *)SMBFS_PROTOCOL_NAME);
4039c9af259SGordon Ross 			(void) sa_add_protocol_property(protoset, sect);
4044bff34e3Sthurlow 			if (lastpgname)
4054bff34e3Sthurlow 				free(lastpgname);
4064bff34e3Sthurlow 			lastpgname = strdup(pgname);
4074bff34e3Sthurlow 		}
4084bff34e3Sthurlow 		name = scf_simple_prop_name(prop);
4094bff34e3Sthurlow 		value = scf_simple_prop_next_astring(prop);
4104bff34e3Sthurlow 
4114bff34e3Sthurlow 		/* If we get a section name, apply it and consume it */
4124bff34e3Sthurlow 		if (strncmp("section", name, 7) == 0 && value != NULL) {
4134bff34e3Sthurlow 			(void) xmlSetProp(sect, (xmlChar *)"name",
4144bff34e3Sthurlow 			    (xmlChar *)value);
4154bff34e3Sthurlow 			continue;
4164bff34e3Sthurlow 		}
4179c9af259SGordon Ross 
4184bff34e3Sthurlow 		/*
4199c9af259SGordon Ross 		 * We have an ordinary property.  Add to the section.
4209c9af259SGordon Ross 		 *
4219c9af259SGordon Ross 		 * The memory allocated by sa_create_property is
4229c9af259SGordon Ross 		 * linked into the list of children under "sect",
4239c9af259SGordon Ross 		 * and will eventually be freed via that list.
4244bff34e3Sthurlow 		 */
4254bff34e3Sthurlow 		node = sa_create_property(name, value);
4264bff34e3Sthurlow 		(void) sa_add_protocol_property(sect, node);
4274bff34e3Sthurlow 	}
4284bff34e3Sthurlow 	scf_simple_app_props_free(props);
4299c9af259SGordon Ross 
4304bff34e3Sthurlow 	if (lastpgname)
4314bff34e3Sthurlow 		free(lastpgname);
4324bff34e3Sthurlow 	return (0);
4334bff34e3Sthurlow }
4344bff34e3Sthurlow 
4354bff34e3Sthurlow /*
4364bff34e3Sthurlow  * Save the set of properties for a particular section, which is
4374bff34e3Sthurlow  * stored as a single property group.  Properties will have been
4384bff34e3Sthurlow  * changed earlier by one or more calls to smbfs_save_property(),
4394bff34e3Sthurlow  * which only set the value in our array and marked them as
4404bff34e3Sthurlow  * SMBC_MODIFIED.
4414bff34e3Sthurlow  */
4424bff34e3Sthurlow int
smbfs_save_propset()4434bff34e3Sthurlow smbfs_save_propset()
4444bff34e3Sthurlow {
4454bff34e3Sthurlow 	smb_scfhandle_t *handle = NULL;
4464bff34e3Sthurlow 	char propgroup[256];
4474bff34e3Sthurlow 	char *section = smbclnt_proto_options[PROTO_OPT_SECTION].value;
4484bff34e3Sthurlow 	char *uu = NULL;
4494bff34e3Sthurlow 	uuid_t uuid;
4504bff34e3Sthurlow 	int i, ret = 0;
4514bff34e3Sthurlow 	sa_property_t propset;
4524bff34e3Sthurlow 	int new = 0, nonnull = 0;
4534bff34e3Sthurlow 
4544bff34e3Sthurlow 	propset = sa_get_protocol_section(protoset, section);
4559c9af259SGordon Ross 	(void) strlcpy(propgroup, SMBC_PG_PREFIX, sizeof (propgroup));
4564bff34e3Sthurlow 	propgroup[SMBC_PG_PREFIX_LEN] = '\0';
4574bff34e3Sthurlow 	uu = sa_get_property_attr(propset, "extra");
4584bff34e3Sthurlow 	if (uu != NULL) {
4599c9af259SGordon Ross 		(void) strlcat(propgroup, uu, sizeof (propgroup));
4604bff34e3Sthurlow 		free(uu);
4614bff34e3Sthurlow 	} else {
4624bff34e3Sthurlow 		new = 1;
4634bff34e3Sthurlow 		smbclnt_proto_options[PROTO_OPT_SECTION].flags |= SMBC_MODIFIED;
4644bff34e3Sthurlow 		uuid_generate(uuid);
4654bff34e3Sthurlow 		uuid_unparse(uuid, &propgroup[SMBC_PG_PREFIX_LEN]);
4664bff34e3Sthurlow 	}
4674bff34e3Sthurlow 
4684bff34e3Sthurlow 	handle = smb_smf_scf_init(SMBC_FMRI_PREFIX);
4694bff34e3Sthurlow 	if (handle == NULL) {
4704bff34e3Sthurlow 		return (1);
4714bff34e3Sthurlow 	}
4724bff34e3Sthurlow 
4734bff34e3Sthurlow 	if ((ret = smb_smf_instance_create(handle, SMBC_FMRI_PREFIX,
4744bff34e3Sthurlow 	    SMBC_PG_INSTANCE)) != SMBC_SMF_OK) {
4754bff34e3Sthurlow 		goto out;
4764bff34e3Sthurlow 	}
4774bff34e3Sthurlow 
4784bff34e3Sthurlow 	if ((ret = smb_smf_create_instance_pgroup(handle, propgroup))
4794bff34e3Sthurlow 	    != SMBC_SMF_OK) {
4804bff34e3Sthurlow 		goto out;
4814bff34e3Sthurlow 	}
4824bff34e3Sthurlow 
4834bff34e3Sthurlow 	if ((ret = smb_smf_start_transaction(handle)) != SMBC_SMF_OK) {
4844bff34e3Sthurlow 		goto out;
4854bff34e3Sthurlow 	}
4864bff34e3Sthurlow 
4874bff34e3Sthurlow 	for (i = PROTO_OPT_SECTION+1; i <= SMBC_OPT_MAX; i++) {
4884bff34e3Sthurlow 		if ((smbclnt_proto_options[i].flags & SMBC_MODIFIED) == 0)
4894bff34e3Sthurlow 			continue;
4904bff34e3Sthurlow 		if (strcmp(smbclnt_proto_options[i].value, "") == 0)
4914bff34e3Sthurlow 			ret = smb_smf_delete_property(handle,
4924bff34e3Sthurlow 			    smbclnt_proto_options[i].name);
4934bff34e3Sthurlow 		else {
4944bff34e3Sthurlow 			ret = smb_smf_set_string_property(handle,
4954bff34e3Sthurlow 			    smbclnt_proto_options[i].name,
4964bff34e3Sthurlow 			    smbclnt_proto_options[i].value);
4974bff34e3Sthurlow 			nonnull = 1;
4984bff34e3Sthurlow 		}
4994bff34e3Sthurlow 		free(smbclnt_proto_options[i].value);
5004bff34e3Sthurlow 		smbclnt_proto_options[i].value = NULL;
5014bff34e3Sthurlow 		smbclnt_proto_options[i].flags &= ~SMBC_MODIFIED;
5024bff34e3Sthurlow 		if (ret != SMBC_SMF_OK)
5034bff34e3Sthurlow 			goto outtrans;
5044bff34e3Sthurlow 	}
5054bff34e3Sthurlow 	/*
5064bff34e3Sthurlow 	 * Suppress new, null entries by not saving the section name.
5074bff34e3Sthurlow 	 */
5084bff34e3Sthurlow 	if (!new || nonnull) {
5094bff34e3Sthurlow 		ret = smb_smf_set_string_property(handle,
5104bff34e3Sthurlow 		    smbclnt_proto_options[PROTO_OPT_SECTION].name,
5114bff34e3Sthurlow 		    smbclnt_proto_options[PROTO_OPT_SECTION].value);
5124bff34e3Sthurlow 		free(smbclnt_proto_options[PROTO_OPT_SECTION].value);
5134bff34e3Sthurlow 		smbclnt_proto_options[PROTO_OPT_SECTION].value = NULL;
5144bff34e3Sthurlow 		smbclnt_proto_options[PROTO_OPT_SECTION].flags &=
5154bff34e3Sthurlow 		    ~SMBC_MODIFIED;
5164bff34e3Sthurlow 	}
5174bff34e3Sthurlow 	propset_changed = 0;
5184bff34e3Sthurlow 
5194bff34e3Sthurlow outtrans:
5204bff34e3Sthurlow 	ret = smb_smf_end_transaction(handle);
5214bff34e3Sthurlow out:
5224bff34e3Sthurlow 	smb_smf_scf_fini(handle);
5234bff34e3Sthurlow 	return (ret);
5244bff34e3Sthurlow }
5254bff34e3Sthurlow 
5264bff34e3Sthurlow /*
5274bff34e3Sthurlow  * initprotofromdefault()
5284bff34e3Sthurlow  *
5294bff34e3Sthurlow  * read the default file(s) and add the defined values to the
5304bff34e3Sthurlow  * protoset.  Note that default values are known from the built in
5314bff34e3Sthurlow  * table in case the file doesn't have a definition.
5324bff34e3Sthurlow  */
5334bff34e3Sthurlow 
5344bff34e3Sthurlow static int
initprotofromdefault()5354bff34e3Sthurlow initprotofromdefault()
5364bff34e3Sthurlow {
5374bff34e3Sthurlow 	protoset = sa_create_protocol_properties(SMBFS_PROTOCOL_NAME);
5384bff34e3Sthurlow 	if (protoset == NULL)
5394bff34e3Sthurlow 		return (SA_NO_MEMORY);
5404bff34e3Sthurlow 	if (smbclnt_config_load() != 0)
5414bff34e3Sthurlow 		return (SA_OK);
5424bff34e3Sthurlow 
5434bff34e3Sthurlow 	return (SA_OK);
5444bff34e3Sthurlow }
5454bff34e3Sthurlow 
5464bff34e3Sthurlow /*
5474bff34e3Sthurlow  *
5484bff34e3Sthurlow  * smbfs_features()
5494bff34e3Sthurlow  *
5504bff34e3Sthurlow  * Report the plugin's features
5514bff34e3Sthurlow  */
5524bff34e3Sthurlow static uint64_t
smbfs_features()5534bff34e3Sthurlow smbfs_features()
5544bff34e3Sthurlow {
5554bff34e3Sthurlow 	return (SA_FEATURE_HAS_SECTIONS | SA_FEATURE_ADD_PROPERTIES);
5564bff34e3Sthurlow }
5574bff34e3Sthurlow 
5584bff34e3Sthurlow /*
5594bff34e3Sthurlow  * smbfs_init()
5604bff34e3Sthurlow  *
5614bff34e3Sthurlow  * Initialize the smb plugin.
5624bff34e3Sthurlow  */
5634bff34e3Sthurlow 
5644bff34e3Sthurlow static int
smbfs_init()5654bff34e3Sthurlow smbfs_init()
5664bff34e3Sthurlow {
5674bff34e3Sthurlow 	int ret = SA_OK;
5684bff34e3Sthurlow 
5694bff34e3Sthurlow 	if (sa_plugin_ops.sa_init != smbfs_init) {
5704bff34e3Sthurlow 		return (SA_SYSTEM_ERR);
5714bff34e3Sthurlow 	}
5724bff34e3Sthurlow 
5734bff34e3Sthurlow 	if (initprotofromdefault() != SA_OK) {
5744bff34e3Sthurlow 		return (SA_SYSTEM_ERR);
5754bff34e3Sthurlow 	}
5764bff34e3Sthurlow 
5774bff34e3Sthurlow 	return (ret);
5784bff34e3Sthurlow }
5794bff34e3Sthurlow 
5804bff34e3Sthurlow /*
5814bff34e3Sthurlow  * smbfs_fini()
5824bff34e3Sthurlow  *
5834bff34e3Sthurlow  * uninitialize the smb plugin. Want to avoid memory leaks.
5844bff34e3Sthurlow  */
5854bff34e3Sthurlow 
5864bff34e3Sthurlow static void
smbfs_fini()5874bff34e3Sthurlow smbfs_fini()
5884bff34e3Sthurlow {
5894bff34e3Sthurlow 	if (propset_changed)
5904bff34e3Sthurlow 		(void) smbfs_save_propset();
5919c9af259SGordon Ross 	xmlFreeNode(protoset);
5929c9af259SGordon Ross 	protoset = NULL;
5934bff34e3Sthurlow }
5944bff34e3Sthurlow 
5954bff34e3Sthurlow /*
5964bff34e3Sthurlow  * smbfs_get_proto_set()
5974bff34e3Sthurlow  *
5984bff34e3Sthurlow  * Return an optionset with all the protocol specific properties in
5994bff34e3Sthurlow  * it.
6004bff34e3Sthurlow  */
6014bff34e3Sthurlow 
6024bff34e3Sthurlow static sa_protocol_properties_t
smbfs_get_proto_set()6034bff34e3Sthurlow smbfs_get_proto_set()
6044bff34e3Sthurlow {
6054bff34e3Sthurlow 	return (protoset);
6064bff34e3Sthurlow }
6074bff34e3Sthurlow 
6084bff34e3Sthurlow /*
6094bff34e3Sthurlow  * smbfs_validate_proto_prop(index, name, value)
6104bff34e3Sthurlow  *
6114bff34e3Sthurlow  * Verify that the property specifed by name can take the new
6124bff34e3Sthurlow  * value. This is a sanity check to prevent bad values getting into
6134bff34e3Sthurlow  * the default files.
6144bff34e3Sthurlow  */
6154bff34e3Sthurlow static int
smbfs_validate_proto_prop(int index,char * section,char * name,char * value)6164bff34e3Sthurlow smbfs_validate_proto_prop(int index, char *section, char *name, char *value)
6174bff34e3Sthurlow {
6184bff34e3Sthurlow 	if ((section == NULL) || (name == NULL) || (index < 0))
6194bff34e3Sthurlow 		return (SA_BAD_VALUE);
6204bff34e3Sthurlow 
6214bff34e3Sthurlow 	if (smbclnt_proto_options[index].validator == NULL)
6224bff34e3Sthurlow 		return (SA_OK);
6234bff34e3Sthurlow 
6244bff34e3Sthurlow 	return (smbclnt_proto_options[index].validator(index, section, value));
6254bff34e3Sthurlow }
6264bff34e3Sthurlow 
6274bff34e3Sthurlow /*
6284bff34e3Sthurlow  * Save a property to our array; it will be stored to SMF later by
6294bff34e3Sthurlow  * smbfs_save_propset().
6304bff34e3Sthurlow  */
6314bff34e3Sthurlow int
smbfs_save_property(int index,char * section,char * value)6324bff34e3Sthurlow smbfs_save_property(int index, char *section, char *value)
6334bff34e3Sthurlow {
6344bff34e3Sthurlow 	char *s;
6354bff34e3Sthurlow 
6364bff34e3Sthurlow 	if (index == PROTO_OPT_WORKGROUP) {
6374bff34e3Sthurlow 		index = PROTO_OPT_DOMAIN;
6384bff34e3Sthurlow 	}
6394bff34e3Sthurlow 	propset_changed = 1;
6404bff34e3Sthurlow 	s = strdup(section);
6414bff34e3Sthurlow 	if (s == NULL)
6424bff34e3Sthurlow 		return (-1);
6434bff34e3Sthurlow 	smbclnt_proto_options[PROTO_OPT_SECTION].value = s;
6444bff34e3Sthurlow 	s = strdup(value);
6454bff34e3Sthurlow 	if (s == NULL)
6464bff34e3Sthurlow 		return (-1);
6474bff34e3Sthurlow 	smbclnt_proto_options[index].value = s;
6484bff34e3Sthurlow 	smbclnt_proto_options[index].flags |= SMBC_MODIFIED;
6494bff34e3Sthurlow 	return (0);
6504bff34e3Sthurlow }
6514bff34e3Sthurlow 
6524bff34e3Sthurlow /*
6534bff34e3Sthurlow  * smbfs_set_proto_prop(prop)
6544bff34e3Sthurlow  *
6554bff34e3Sthurlow  * check that prop is valid.
6564bff34e3Sthurlow  */
6574bff34e3Sthurlow /*ARGSUSED*/
6584bff34e3Sthurlow static int
smbfs_set_proto_prop(sa_property_t prop)6594bff34e3Sthurlow smbfs_set_proto_prop(sa_property_t prop)
6604bff34e3Sthurlow {
6614bff34e3Sthurlow 	int ret = SA_OK;
6624bff34e3Sthurlow 	char *name;
6634bff34e3Sthurlow 	char *value;
6644bff34e3Sthurlow 	char *section;
6654bff34e3Sthurlow 	int i = -1;
6664bff34e3Sthurlow 
6674bff34e3Sthurlow 	section = sa_get_property_attr(prop, "section");
6684bff34e3Sthurlow 	if (section == NULL)
6694bff34e3Sthurlow 		return (SA_NO_SECTION);
6704bff34e3Sthurlow 	name = sa_get_property_attr(prop, "type");
6714bff34e3Sthurlow 	value = sa_get_property_attr(prop, "value");
6724bff34e3Sthurlow 	if (name != NULL && value != NULL) {
6734bff34e3Sthurlow 		i = findprotoopt(name);
6744bff34e3Sthurlow 		if (i >= 0) {
6754bff34e3Sthurlow 			ret = smbfs_validate_proto_prop(i, section,
6764bff34e3Sthurlow 			    name, value);
6774bff34e3Sthurlow 			if (ret == SA_OK) {
6784bff34e3Sthurlow 				if (smbfs_save_property(i, section,
6794bff34e3Sthurlow 				    value) != 0) {
6804bff34e3Sthurlow 					ret = SA_SYSTEM_ERR;
6814bff34e3Sthurlow 					errno = EIO;
6824bff34e3Sthurlow 				}
6834bff34e3Sthurlow 			}
6844bff34e3Sthurlow 		} else
6854bff34e3Sthurlow 			ret = SA_INVALID_NAME;
6864bff34e3Sthurlow 	}
6874bff34e3Sthurlow 	if (name != NULL)
6884bff34e3Sthurlow 		sa_free_attr_string(name);
6894bff34e3Sthurlow 	if (value != NULL)
6904bff34e3Sthurlow 		sa_free_attr_string(value);
6919c9af259SGordon Ross 	if (section != NULL)
6929c9af259SGordon Ross 		sa_free_attr_string(section);
6934bff34e3Sthurlow 
6944bff34e3Sthurlow 	return (ret);
6954bff34e3Sthurlow }
6964bff34e3Sthurlow 
6974bff34e3Sthurlow /*
6984bff34e3Sthurlow  * smbfs_get_status()
6994bff34e3Sthurlow  *
7004bff34e3Sthurlow  * What is the current status of the smbd? We use the SMF state here.
7014bff34e3Sthurlow  * Caller must free the returned value.
7024bff34e3Sthurlow  */
7034bff34e3Sthurlow 
7044bff34e3Sthurlow static char *
smbfs_get_status()7054bff34e3Sthurlow smbfs_get_status()
7064bff34e3Sthurlow {
707652601fbSRobert Mustacchi 	return (smf_get_state(SMBC_DEFAULT_INSTANCE_FMRI));
7084bff34e3Sthurlow }
7094bff34e3Sthurlow 
7104bff34e3Sthurlow /*
7114bff34e3Sthurlow  * Delete a section by its name, which we will have read into an
7124bff34e3Sthurlow  * XML optionset above.  We need to find it and find its UUID to
7134bff34e3Sthurlow  * be able to generate the property group name in order to call
7144bff34e3Sthurlow  * smbfs_delete_property_group().
7154bff34e3Sthurlow  */
7164bff34e3Sthurlow static int
smbfs_delete_section(char * section)7174bff34e3Sthurlow smbfs_delete_section(char *section)
7184bff34e3Sthurlow {
7194bff34e3Sthurlow 	char propgroup[256];
7204bff34e3Sthurlow 	char *uu = NULL;
7214bff34e3Sthurlow 	sa_property_t propset;
7224bff34e3Sthurlow 	int ret = SA_SYSTEM_ERR;
7234bff34e3Sthurlow 
7244bff34e3Sthurlow 	propset = sa_get_protocol_section(protoset, section);
7259c9af259SGordon Ross 	(void) strlcpy(propgroup, SMBC_PG_PREFIX, sizeof (propgroup));
7264bff34e3Sthurlow 	propgroup[SMBC_PG_PREFIX_LEN] = '\0';
7274bff34e3Sthurlow 	uu = sa_get_property_attr(propset, "extra");
7284bff34e3Sthurlow 	if (uu == NULL)
7294bff34e3Sthurlow 		goto out;
7309c9af259SGordon Ross 	(void) strlcat(propgroup, uu, sizeof (propgroup));
7314bff34e3Sthurlow 	free(uu);
7324bff34e3Sthurlow 	if ((ret = smbfs_delete_property_group(propgroup)) != SMBC_SMF_OK)
7334bff34e3Sthurlow 		goto out;
7344bff34e3Sthurlow 	ret = SA_OK;
7354bff34e3Sthurlow out:
7364bff34e3Sthurlow 	return (ret);
7374bff34e3Sthurlow }
7384bff34e3Sthurlow 
7394bff34e3Sthurlow /*
7404bff34e3Sthurlow  * Delete a property group by its name.  Called to do a 'delsect'
7414bff34e3Sthurlow  * or called when smbclnt_config_load() notices an empty section
7424bff34e3Sthurlow  * at the end of the properties.
7434bff34e3Sthurlow  */
7444bff34e3Sthurlow static int
smbfs_delete_property_group(char * propgroup)7454bff34e3Sthurlow smbfs_delete_property_group(char *propgroup)
7464bff34e3Sthurlow {
7474bff34e3Sthurlow 	smb_scfhandle_t *handle = NULL;
7484bff34e3Sthurlow 	int ret = SA_SYSTEM_ERR;
7494bff34e3Sthurlow 
7504bff34e3Sthurlow 	handle = smb_smf_scf_init(SMBC_FMRI_PREFIX);
7514bff34e3Sthurlow 	if (handle == NULL)
7524bff34e3Sthurlow 		goto out;
7534bff34e3Sthurlow 
7544bff34e3Sthurlow 	if ((ret = smb_smf_instance_create(handle, SMBC_FMRI_PREFIX,
7554bff34e3Sthurlow 	    SMBC_PG_INSTANCE)) != SMBC_SMF_OK)
7564bff34e3Sthurlow 		goto out;
7574bff34e3Sthurlow 
7584bff34e3Sthurlow 	if ((ret = smb_smf_delete_instance_pgroup(handle, propgroup))
7594bff34e3Sthurlow 	    != SMBC_SMF_OK)
7604bff34e3Sthurlow 		goto out;
7614bff34e3Sthurlow 	ret = SA_OK;
7624bff34e3Sthurlow out:
7634bff34e3Sthurlow 	smb_smf_scf_fini(handle);
7644bff34e3Sthurlow 	return (ret);
7654bff34e3Sthurlow }
766