xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c (revision 5419c0309c3a28f6bfee2e35aefebca2200d046d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 /*
27  * CIFS configuration management library
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <synch.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <syslog.h>
37 #include <netdb.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <libscf.h>
41 #include <assert.h>
42 #include <uuid/uuid.h>
43 #include <smbsrv/libsmb.h>
44 
45 typedef struct smb_cfg_param {
46 	smb_cfg_id_t sc_id;
47 	char *sc_name;
48 	int sc_type;
49 	uint32_t sc_flags;
50 } smb_cfg_param_t;
51 
52 struct str_val {
53 	char *str;
54 	uint32_t val;
55 };
56 
57 /*
58  * config parameter flags
59  */
60 #define	SMB_CF_PROTECTED	0x01
61 #define	SMB_CF_EXEC		0x02
62 
63 /* idmap SMF fmri and Property Group */
64 #define	IDMAP_FMRI_PREFIX		"system/idmap"
65 #define	MACHINE_SID			"machine_sid"
66 #define	MACHINE_UUID			"machine_uuid"
67 #define	IDMAP_DOMAIN			"domain_name"
68 #define	IDMAP_PREF_DC			"preferred_dc"
69 #define	IDMAP_SITE_NAME			"site_name"
70 #define	IDMAP_PG_NAME			"config"
71 
72 #define	SMB_SECMODE_WORKGRP_STR		"workgroup"
73 #define	SMB_SECMODE_DOMAIN_STR		"domain"
74 
75 #define	SMB_ENC_LEN	1024
76 #define	SMB_DEC_LEN	256
77 
78 static char *b64_data =
79 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80 
81 static smb_cfg_param_t smb_cfg_table[] =
82 {
83 	{SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
84 
85 	/* Oplock configuration, Kernel Only */
86 	{SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
87 
88 	/* Autohome configuration */
89 	{SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
90 
91 	/* Domain/PDC configuration */
92 	{SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0},
93 	{SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0},
94 	{SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0},
95 	{SMB_CI_DOMAIN_FQDN, "fqdn", SCF_TYPE_ASTRING, 0},
96 	{SMB_CI_DOMAIN_FOREST, "forest", SCF_TYPE_ASTRING, 0},
97 	{SMB_CI_DOMAIN_GUID, "domain_guid", SCF_TYPE_ASTRING, 0},
98 	{SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0},
99 
100 	/* WINS configuration */
101 	{SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0},
102 	{SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0},
103 	{SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0},
104 
105 	/* Kmod specific configuration */
106 	{SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0},
107 	{SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0},
108 	{SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0},
109 	{SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0},
110 
111 	{SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0},
112 	{SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0},
113 
114 	/* Kmod tuning configuration */
115 	{SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0},
116 
117 	/* SMBd configuration */
118 	{SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0},
119 	{SMB_CI_NETBIOS_ENABLE, "netbios_enable", SCF_TYPE_BOOLEAN, 0},
120 	{SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0},
121 	{SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0},
122 	{SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0},
123 
124 	/* ADS Configuration */
125 	{SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0},
126 
127 	/* Dynamic DNS */
128 	{SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0},
129 
130 	{SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
131 	    SMB_CF_PROTECTED},
132 
133 	{SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
134 	{SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
135 	{SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
136 	{SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
137 	{SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
138 	{SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
139 	{SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
140 	{SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
141 	{SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
142 	{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
143 	{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
144 	{SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
145 	{SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
146 	{SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
147 	{SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
148 	{SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},
149 	{SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0},
150 
151 	/* SMB_CI_MAX */
152 };
153 
154 /*
155  * We store the max SMB protocol version in SMF as a string,
156  * (for convenience of svccfg etc) but the programmatic get/set
157  * interfaces use the numeric form.
158  *
159  * The numeric values are as defined in the [MS-SMB2] spec.
160  * except for how we represent "1" (for SMB1) which is an
161  * arbitrary value below SMB2_VERS_BASE.
162  */
163 static struct str_val
164 smb_versions[] = {
165 	{ "3.0",	SMB_VERS_3_0 },
166 	{ "2.1",	SMB_VERS_2_1 },
167 	{ "2.002",	SMB_VERS_2_002 },
168 	{ "1",		SMB_VERS_1 },
169 	{ NULL,		0 }
170 };
171 
172 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
173 
174 static boolean_t smb_is_base64(unsigned char c);
175 static char *smb_base64_encode(char *str_to_encode);
176 static char *smb_base64_decode(char *encoded_str);
177 static int smb_config_get_idmap_preferred_dc(char *, int);
178 static int smb_config_set_idmap_preferred_dc(char *);
179 static int smb_config_get_idmap_site_name(char *, int);
180 static int smb_config_set_idmap_site_name(char *);
181 
182 static uint32_t
183 smb_convert_version_str(const char *version)
184 {
185 	uint32_t dialect = 0;
186 	int i;
187 
188 	for (i = 0; smb_versions[i].str != NULL; i++) {
189 		if (strcmp(version, smb_versions[i].str) == 0)
190 			dialect = smb_versions[i].val;
191 	}
192 
193 	return (dialect);
194 }
195 
196 char *
197 smb_config_getname(smb_cfg_id_t id)
198 {
199 	smb_cfg_param_t *cfg;
200 	cfg = smb_config_getent(id);
201 	return (cfg->sc_name);
202 }
203 
204 static boolean_t
205 smb_is_base64(unsigned char c)
206 {
207 	return (isalnum(c) || (c == '+') || (c == '/'));
208 }
209 
210 /*
211  * smb_base64_encode
212  *
213  * Encode a string using base64 algorithm.
214  * Caller should free the returned buffer when done.
215  */
216 static char *
217 smb_base64_encode(char *str_to_encode)
218 {
219 	int ret_cnt = 0;
220 	int i = 0, j = 0;
221 	char arr_3[3], arr_4[4];
222 	int len = strlen(str_to_encode);
223 	char *ret = malloc(SMB_ENC_LEN);
224 
225 	if (ret == NULL) {
226 		return (NULL);
227 	}
228 
229 	while (len--) {
230 		arr_3[i++] = *(str_to_encode++);
231 		if (i == 3) {
232 			arr_4[0] = (arr_3[0] & 0xfc) >> 2;
233 			arr_4[1] = ((arr_3[0] & 0x03) << 4) +
234 			    ((arr_3[1] & 0xf0) >> 4);
235 			arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
236 			    ((arr_3[2] & 0xc0) >> 6);
237 			arr_4[3] = arr_3[2] & 0x3f;
238 
239 			for (i = 0; i < 4; i++)
240 				ret[ret_cnt++] = b64_data[arr_4[i]];
241 			i = 0;
242 		}
243 	}
244 
245 	if (i) {
246 		for (j = i; j < 3; j++)
247 			arr_3[j] = '\0';
248 
249 		arr_4[0] = (arr_3[0] & 0xfc) >> 2;
250 		arr_4[1] = ((arr_3[0] & 0x03) << 4) +
251 		    ((arr_3[1] & 0xf0) >> 4);
252 		arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
253 		    ((arr_3[2] & 0xc0) >> 6);
254 		arr_4[3] = arr_3[2] & 0x3f;
255 
256 		for (j = 0; j < (i + 1); j++)
257 			ret[ret_cnt++] = b64_data[arr_4[j]];
258 
259 		while (i++ < 3)
260 			ret[ret_cnt++] = '=';
261 	}
262 
263 	ret[ret_cnt++] = '\0';
264 	return (ret);
265 }
266 
267 /*
268  * smb_base64_decode
269  *
270  * Decode using base64 algorithm.
271  * Caller should free the returned buffer when done.
272  */
273 static char *
274 smb_base64_decode(char *encoded_str)
275 {
276 	int len = strlen(encoded_str);
277 	int i = 0, j = 0;
278 	int en_ind = 0;
279 	char arr_4[4], arr_3[3];
280 	int ret_cnt = 0;
281 	char *ret = malloc(SMB_DEC_LEN);
282 	char *p;
283 
284 	if (ret == NULL) {
285 		return (NULL);
286 	}
287 
288 	while (len-- && (encoded_str[en_ind] != '=') &&
289 	    smb_is_base64(encoded_str[en_ind])) {
290 		arr_4[i++] = encoded_str[en_ind];
291 		en_ind++;
292 		if (i == 4) {
293 			for (i = 0; i < 4; i++) {
294 				if ((p = strchr(b64_data, arr_4[i])) == NULL)
295 					return (NULL);
296 
297 				arr_4[i] = (int)(p - b64_data);
298 			}
299 
300 			arr_3[0] = (arr_4[0] << 2) +
301 			    ((arr_4[1] & 0x30) >> 4);
302 			arr_3[1] = ((arr_4[1] & 0xf) << 4) +
303 			    ((arr_4[2] & 0x3c) >> 2);
304 			arr_3[2] = ((arr_4[2] & 0x3) << 6) +
305 			    arr_4[3];
306 
307 			for (i = 0; i < 3; i++)
308 				ret[ret_cnt++] = arr_3[i];
309 
310 			i = 0;
311 		}
312 	}
313 
314 	if (i) {
315 		for (j = i; j < 4; j++)
316 			arr_4[j] = 0;
317 
318 		for (j = 0; j < 4; j++) {
319 			if ((p = strchr(b64_data, arr_4[j])) == NULL)
320 				return (NULL);
321 
322 			arr_4[j] = (int)(p - b64_data);
323 		}
324 		arr_3[0] = (arr_4[0] << 2) +
325 		    ((arr_4[1] & 0x30) >> 4);
326 		arr_3[1] = ((arr_4[1] & 0xf) << 4) +
327 		    ((arr_4[2] & 0x3c) >> 2);
328 		arr_3[2] = ((arr_4[2] & 0x3) << 6) +
329 		    arr_4[3];
330 		for (j = 0; j < (i - 1); j++)
331 			ret[ret_cnt++] = arr_3[j];
332 	}
333 
334 	ret[ret_cnt++] = '\0';
335 	return (ret);
336 }
337 
338 static char *
339 smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp)
340 {
341 	smb_scfhandle_t *handle;
342 	char *value;
343 
344 	if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL)
345 		return (NULL);
346 
347 	handle = smb_smf_scf_init(svc_fmri_prefix);
348 	if (handle == NULL) {
349 		free(value);
350 		return (NULL);
351 	}
352 
353 	(void) smb_smf_create_service_pgroup(handle, svc_propgrp);
354 
355 	if (smb_smf_get_string_property(handle, name, value,
356 	    sizeof (char) * MAX_VALUE_BUFLEN) != 0) {
357 		smb_smf_scf_fini(handle);
358 		free(value);
359 		return (NULL);
360 	}
361 
362 	smb_smf_scf_fini(handle);
363 	return (value);
364 
365 }
366 
367 static int
368 smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp,
369     char *name, char *value)
370 {
371 	smb_scfhandle_t *handle = NULL;
372 	int rc = 0;
373 
374 
375 	handle = smb_smf_scf_init(svc_fmri_prefix);
376 	if (handle == NULL) {
377 		return (1);
378 	}
379 
380 	(void) smb_smf_create_service_pgroup(handle, svc_propgrp);
381 
382 	if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) {
383 		smb_smf_scf_fini(handle);
384 		return (1);
385 	}
386 
387 	if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK)
388 		rc = 1;
389 
390 	if (smb_smf_end_transaction(handle) != SMBD_SMF_OK)
391 		rc = 1;
392 
393 	smb_smf_scf_fini(handle);
394 	return (rc);
395 }
396 
397 /*
398  * smb_config_getstr
399  *
400  * Fetch the specified string configuration item from SMF
401  */
402 int
403 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
404 {
405 	smb_scfhandle_t *handle;
406 	smb_cfg_param_t *cfg;
407 	int rc = SMBD_SMF_OK;
408 	char *pg;
409 	char protbuf[SMB_ENC_LEN];
410 	char *tmp;
411 
412 	*cbuf = '\0';
413 	cfg = smb_config_getent(id);
414 	assert(cfg->sc_type == SCF_TYPE_ASTRING);
415 
416 	if (id == SMB_CI_ADS_SITE)
417 		return (smb_config_get_idmap_site_name(cbuf, bufsz));
418 	if (id == SMB_CI_DOMAIN_SRV)
419 		return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
420 
421 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
422 	if (handle == NULL)
423 		return (SMBD_SMF_SYSTEM_ERR);
424 
425 	if (cfg->sc_flags & SMB_CF_PROTECTED) {
426 		if ((rc = smb_smf_create_service_pgroup(handle,
427 		    SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
428 			goto error;
429 
430 		if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
431 		    protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
432 			goto error;
433 
434 		if (*protbuf != '\0') {
435 			tmp = smb_base64_decode(protbuf);
436 			(void) strlcpy(cbuf, tmp, bufsz);
437 			free(tmp);
438 		}
439 	} else {
440 		pg = (cfg->sc_flags & SMB_CF_EXEC) ? SMBD_EXEC_PG_NAME :
441 		    SMBD_PG_NAME;
442 		rc = smb_smf_create_service_pgroup(handle, pg);
443 		if (rc == SMBD_SMF_OK)
444 			rc = smb_smf_get_string_property(handle, cfg->sc_name,
445 			    cbuf, bufsz);
446 	}
447 
448 error:
449 	smb_smf_scf_fini(handle);
450 	return (rc);
451 }
452 
453 /*
454  * Translate the value of an astring SMF property into a binary
455  * IP address. If the value is neither a valid IPv4 nor IPv6
456  * address, attempt to look it up as a hostname using the
457  * configured address type.
458  */
459 int
460 smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr)
461 {
462 	int rc, error;
463 	int a_family;
464 	char ipstr[MAXHOSTNAMELEN];
465 	struct hostent *h;
466 	smb_cfg_param_t *cfg;
467 
468 	if (ipaddr == NULL)
469 		return (SMBD_SMF_INVALID_ARG);
470 
471 	bzero(ipaddr, sizeof (smb_inaddr_t));
472 	rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr));
473 	if (rc == SMBD_SMF_OK) {
474 		if (*ipstr == '\0')
475 			return (SMBD_SMF_INVALID_ARG);
476 
477 		if (inet_pton(AF_INET, ipstr, &ipaddr->a_ipv4) == 1) {
478 			ipaddr->a_family = AF_INET;
479 			return (SMBD_SMF_OK);
480 		}
481 
482 		if (inet_pton(AF_INET6, ipstr, &ipaddr->a_ipv6) == 1) {
483 			ipaddr->a_family = AF_INET6;
484 			return (SMBD_SMF_OK);
485 		}
486 
487 		/*
488 		 * The value is neither an IPv4 nor IPv6 address;
489 		 * so check if it's a hostname.
490 		 */
491 		a_family = smb_config_getbool(SMB_CI_IPV6_ENABLE) ?
492 		    AF_INET6 : AF_INET;
493 		h = getipnodebyname(ipstr, a_family, AI_DEFAULT,
494 		    &error);
495 		if (h != NULL) {
496 			bcopy(*(h->h_addr_list), &ipaddr->a_ip,
497 			    h->h_length);
498 			ipaddr->a_family = a_family;
499 			freehostent(h);
500 			rc = SMBD_SMF_OK;
501 		} else {
502 			cfg = smb_config_getent(sc_id);
503 			syslog(LOG_ERR, "smbd/%s: %s unable to get %s "
504 			    "address: %d", cfg->sc_name, ipstr,
505 			    a_family == AF_INET ?  "IPv4" : "IPv6", error);
506 			rc = SMBD_SMF_INVALID_ARG;
507 		}
508 	}
509 
510 	return (rc);
511 }
512 
513 /*
514  * smb_config_getnum
515  *
516  * Returns the value of a numeric config param.
517  */
518 int
519 smb_config_getnum(smb_cfg_id_t id, int64_t *cint)
520 {
521 	smb_scfhandle_t *handle;
522 	smb_cfg_param_t *cfg;
523 	int rc = SMBD_SMF_OK;
524 
525 	*cint = 0;
526 	cfg = smb_config_getent(id);
527 	assert(cfg->sc_type == SCF_TYPE_INTEGER);
528 
529 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
530 	if (handle == NULL)
531 		return (SMBD_SMF_SYSTEM_ERR);
532 
533 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
534 	if (rc == SMBD_SMF_OK)
535 		rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint);
536 	smb_smf_scf_fini(handle);
537 
538 	return (rc);
539 }
540 
541 /*
542  * smb_config_getbool
543  *
544  * Returns the value of a boolean config param.
545  */
546 boolean_t
547 smb_config_getbool(smb_cfg_id_t id)
548 {
549 	smb_scfhandle_t *handle;
550 	smb_cfg_param_t *cfg;
551 	int rc = SMBD_SMF_OK;
552 	uint8_t vbool;
553 
554 	cfg = smb_config_getent(id);
555 	assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
556 
557 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
558 	if (handle == NULL)
559 		return (B_FALSE);
560 
561 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
562 	if (rc == SMBD_SMF_OK)
563 		rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool);
564 	smb_smf_scf_fini(handle);
565 
566 	return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE);
567 }
568 
569 /*
570  * smb_config_get
571  *
572  * This function returns the value of the requested config
573  * iterm regardless of its type in string format. This should
574  * be used when the config item type is not known by the caller.
575  */
576 int
577 smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz)
578 {
579 	smb_cfg_param_t *cfg;
580 	int64_t cint;
581 	int rc;
582 
583 	cfg = smb_config_getent(id);
584 	switch (cfg->sc_type) {
585 	case SCF_TYPE_ASTRING:
586 		return (smb_config_getstr(id, cbuf, bufsz));
587 
588 	case SCF_TYPE_INTEGER:
589 		rc = smb_config_getnum(id, &cint);
590 		if (rc == SMBD_SMF_OK)
591 			(void) snprintf(cbuf, bufsz, "%lld", cint);
592 		return (rc);
593 
594 	case SCF_TYPE_BOOLEAN:
595 		if (smb_config_getbool(id))
596 			(void) strlcpy(cbuf, "true", bufsz);
597 		else
598 			(void) strlcpy(cbuf, "false", bufsz);
599 		return (SMBD_SMF_OK);
600 	}
601 
602 	return (SMBD_SMF_INVALID_ARG);
603 }
604 
605 /*
606  * smb_config_setstr
607  *
608  * Set the specified config param with the given
609  * value.
610  */
611 int
612 smb_config_setstr(smb_cfg_id_t id, char *value)
613 {
614 	smb_scfhandle_t *handle;
615 	smb_cfg_param_t *cfg;
616 	int rc = SMBD_SMF_OK;
617 	boolean_t protected;
618 	char *tmp = NULL;
619 	char *pg;
620 
621 	cfg = smb_config_getent(id);
622 	assert(cfg->sc_type == SCF_TYPE_ASTRING);
623 
624 	if (id == SMB_CI_ADS_SITE)
625 		return (smb_config_set_idmap_site_name(value));
626 	if (id == SMB_CI_DOMAIN_SRV)
627 		return (smb_config_set_idmap_preferred_dc(value));
628 
629 	protected = B_FALSE;
630 
631 	switch (cfg->sc_flags) {
632 	case SMB_CF_PROTECTED:
633 		protected = B_TRUE;
634 		pg = SMBD_PROTECTED_PG_NAME;
635 		break;
636 	case SMB_CF_EXEC:
637 		pg = SMBD_EXEC_PG_NAME;
638 		break;
639 	default:
640 		pg = SMBD_PG_NAME;
641 		break;
642 	}
643 
644 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
645 	if (handle == NULL)
646 		return (SMBD_SMF_SYSTEM_ERR);
647 
648 	rc = smb_smf_create_service_pgroup(handle, pg);
649 	if (rc == SMBD_SMF_OK)
650 		rc = smb_smf_start_transaction(handle);
651 
652 	if (rc != SMBD_SMF_OK) {
653 		smb_smf_scf_fini(handle);
654 		return (rc);
655 	}
656 
657 	if (protected && value && (*value != '\0')) {
658 		if ((tmp = smb_base64_encode(value)) == NULL) {
659 			(void) smb_smf_end_transaction(handle);
660 			smb_smf_scf_fini(handle);
661 			return (SMBD_SMF_NO_MEMORY);
662 		}
663 
664 		value = tmp;
665 	}
666 
667 	/*
668 	 * We don't want people who care enough about protecting their data
669 	 * by requiring encryption to accidentally expose their data
670 	 * by lowering the protocol, so prevent them from going below 3.0
671 	 * if encryption is required.
672 	 */
673 	if (id == SMB_CI_MAX_PROTOCOL &&
674 	    smb_config_get_require(SMB_CI_ENCRYPT) == SMB_CONFIG_REQUIRED &&
675 	    smb_config_get_max_protocol() >= SMB_VERS_3_0 &&
676 	    smb_convert_version_str(value) < SMB_VERS_3_0) {
677 		syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0"
678 		    " while smbd/encrypt == required.");
679 		rc = SMBD_SMF_INVALID_ARG;
680 	} else {
681 		rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
682 	}
683 
684 	free(tmp);
685 	(void) smb_smf_end_transaction(handle);
686 	smb_smf_scf_fini(handle);
687 	return (rc);
688 }
689 
690 /*
691  * smb_config_setnum
692  *
693  * Sets a numeric configuration iterm
694  */
695 int
696 smb_config_setnum(smb_cfg_id_t id, int64_t value)
697 {
698 	smb_scfhandle_t *handle;
699 	smb_cfg_param_t *cfg;
700 	int rc = SMBD_SMF_OK;
701 
702 	cfg = smb_config_getent(id);
703 	assert(cfg->sc_type == SCF_TYPE_INTEGER);
704 
705 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
706 	if (handle == NULL)
707 		return (SMBD_SMF_SYSTEM_ERR);
708 
709 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
710 	if (rc == SMBD_SMF_OK)
711 		rc = smb_smf_start_transaction(handle);
712 
713 	if (rc != SMBD_SMF_OK) {
714 		smb_smf_scf_fini(handle);
715 		return (rc);
716 	}
717 
718 	rc = smb_smf_set_integer_property(handle, cfg->sc_name, value);
719 
720 	(void) smb_smf_end_transaction(handle);
721 	smb_smf_scf_fini(handle);
722 	return (rc);
723 }
724 
725 /*
726  * smb_config_setbool
727  *
728  * Sets a boolean configuration iterm
729  */
730 int
731 smb_config_setbool(smb_cfg_id_t id, boolean_t value)
732 {
733 	smb_scfhandle_t *handle;
734 	smb_cfg_param_t *cfg;
735 	int rc = SMBD_SMF_OK;
736 
737 	cfg = smb_config_getent(id);
738 	assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
739 
740 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
741 	if (handle == NULL)
742 		return (SMBD_SMF_SYSTEM_ERR);
743 
744 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
745 	if (rc == SMBD_SMF_OK)
746 		rc = smb_smf_start_transaction(handle);
747 
748 	if (rc != SMBD_SMF_OK) {
749 		smb_smf_scf_fini(handle);
750 		return (rc);
751 	}
752 
753 	rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value);
754 
755 	(void) smb_smf_end_transaction(handle);
756 	smb_smf_scf_fini(handle);
757 	return (rc);
758 }
759 
760 /*
761  * smb_config_set
762  *
763  * This function sets the value of the specified config
764  * iterm regardless of its type in string format. This should
765  * be used when the config item type is not known by the caller.
766  */
767 int
768 smb_config_set(smb_cfg_id_t id, char *value)
769 {
770 	smb_cfg_param_t *cfg;
771 	int64_t cint;
772 
773 	cfg = smb_config_getent(id);
774 	switch (cfg->sc_type) {
775 	case SCF_TYPE_ASTRING:
776 		return (smb_config_setstr(id, value));
777 
778 	case SCF_TYPE_INTEGER:
779 		cint = atoi(value);
780 		return (smb_config_setnum(id, cint));
781 
782 	case SCF_TYPE_BOOLEAN:
783 		return (smb_config_setbool(id, strcasecmp(value, "true") == 0));
784 	}
785 
786 	return (SMBD_SMF_INVALID_ARG);
787 }
788 
789 int
790 smb_config_get_debug()
791 {
792 	int64_t val64;
793 	int val = 0;	/* default */
794 	smb_scfhandle_t *handle = NULL;
795 
796 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
797 	if (handle == NULL) {
798 		return (val);
799 	}
800 
801 	if (smb_smf_create_service_pgroup(handle,
802 	    SMBD_PG_NAME) != SMBD_SMF_OK) {
803 		smb_smf_scf_fini(handle);
804 		return (val);
805 	}
806 
807 	if (smb_smf_get_integer_property(handle, "debug", &val64) != 0) {
808 		smb_smf_scf_fini(handle);
809 		return (val);
810 	}
811 	val = (int)val64;
812 
813 	smb_smf_scf_fini(handle);
814 
815 	return (val);
816 }
817 
818 uint8_t
819 smb_config_get_fg_flag()
820 {
821 	uint8_t run_fg = 0; /* Default is to run in daemon mode */
822 	smb_scfhandle_t *handle = NULL;
823 
824 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
825 	if (handle == NULL) {
826 		return (run_fg);
827 	}
828 
829 	if (smb_smf_create_service_pgroup(handle,
830 	    SMBD_PG_NAME) != SMBD_SMF_OK) {
831 		smb_smf_scf_fini(handle);
832 		return (run_fg);
833 	}
834 
835 	if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) {
836 		smb_smf_scf_fini(handle);
837 		return (run_fg);
838 	}
839 
840 	smb_smf_scf_fini(handle);
841 
842 	return (run_fg);
843 }
844 
845 /*
846  * smb_config_get_ads_enable
847  *
848  * Returns value of the "config/use_ads" parameter
849  * from the IDMAP SMF configuration repository.
850  *
851  */
852 boolean_t
853 smb_config_get_ads_enable(void)
854 {
855 	smb_scfhandle_t *handle = NULL;
856 	uint8_t vbool;
857 	int rc = 0;
858 
859 	handle = smb_smf_scf_init(IDMAP_FMRI_PREFIX);
860 	if (handle == NULL)
861 		return (B_FALSE);
862 
863 	rc = smb_smf_create_service_pgroup(handle, IDMAP_PG_NAME);
864 	if (rc == SMBD_SMF_OK)
865 		rc = smb_smf_get_boolean_property(handle, "use_ads", &vbool);
866 	smb_smf_scf_fini(handle);
867 
868 	return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_TRUE);
869 }
870 
871 /*
872  * smb_config_get_localsid
873  *
874  * Returns value of the "config/machine_sid" parameter
875  * from the IDMAP SMF configuration repository.
876  * Result is allocated; caller should free.
877  */
878 char *
879 smb_config_get_localsid(void)
880 {
881 	return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX,
882 	    IDMAP_PG_NAME));
883 }
884 
885 /*
886  * smb_config_get_localuuid
887  *
888  * Returns value of the "config/machine_uuid" parameter
889  * from the IDMAP SMF configuration repository.
890  *
891  */
892 int
893 smb_config_get_localuuid(uuid_t uu)
894 {
895 	char *s;
896 
897 	uuid_clear(uu);
898 	s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX,
899 	    IDMAP_PG_NAME);
900 	if (s == NULL)
901 		return (-1);
902 
903 	if (uuid_parse(s, uu) < 0) {
904 		free(s);
905 		return (-1);
906 	}
907 
908 	return (0);
909 }
910 
911 static int
912 smb_config_get_idmap_preferred_dc(char *cbuf, int bufsz)
913 {
914 	char *s;
915 	int len, rc = -1;
916 
917 	s = smb_config_getenv_generic(IDMAP_PREF_DC,
918 	    IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
919 	if (s != NULL) {
920 		len = strlcpy(cbuf, s, bufsz);
921 		if (len < bufsz)
922 			rc = 0;
923 		free(s);
924 	}
925 	return (rc);
926 }
927 
928 static int
929 smb_config_set_idmap_preferred_dc(char *value)
930 {
931 	return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
932 	    IDMAP_PREF_DC, value));
933 }
934 
935 static int
936 smb_config_get_idmap_site_name(char *cbuf, int bufsz)
937 {
938 	char *s;
939 	int len, rc = -1;
940 
941 	s = smb_config_getenv_generic(IDMAP_SITE_NAME,
942 	    IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
943 	if (s != NULL) {
944 		len = strlcpy(cbuf, s, bufsz);
945 		if (len < bufsz)
946 			rc = 0;
947 		free(s);
948 	}
949 	return (rc);
950 }
951 
952 static int
953 smb_config_set_idmap_site_name(char *value)
954 {
955 	return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
956 	    IDMAP_SITE_NAME, value));
957 }
958 
959 /*
960  * smb_config_set_idmap_domain
961  *
962  * Set the "config/domain_name" parameter from IDMAP SMF repository.
963  */
964 int
965 smb_config_set_idmap_domain(char *value)
966 {
967 	return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
968 	    IDMAP_DOMAIN, value));
969 }
970 
971 /*
972  * smb_config_refresh_idmap
973  *
974  * Refresh IDMAP SMF service after making changes to its configuration.
975  */
976 int
977 smb_config_refresh_idmap(void)
978 {
979 	char instance[32];
980 
981 	(void) snprintf(instance, sizeof (instance), "%s:default",
982 	    IDMAP_FMRI_PREFIX);
983 	return (smf_refresh_instance(instance));
984 }
985 
986 int
987 smb_config_secmode_fromstr(char *secmode)
988 {
989 	if (secmode == NULL)
990 		return (SMB_SECMODE_WORKGRP);
991 
992 	if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0)
993 		return (SMB_SECMODE_DOMAIN);
994 
995 	return (SMB_SECMODE_WORKGRP);
996 }
997 
998 char *
999 smb_config_secmode_tostr(int secmode)
1000 {
1001 	if (secmode == SMB_SECMODE_DOMAIN)
1002 		return (SMB_SECMODE_DOMAIN_STR);
1003 
1004 	return (SMB_SECMODE_WORKGRP_STR);
1005 }
1006 
1007 int
1008 smb_config_get_secmode()
1009 {
1010 	char p[16];
1011 
1012 	(void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p));
1013 	return (smb_config_secmode_fromstr(p));
1014 }
1015 
1016 int
1017 smb_config_set_secmode(int secmode)
1018 {
1019 	char *p;
1020 
1021 	p = smb_config_secmode_tostr(secmode);
1022 	return (smb_config_setstr(SMB_CI_SECURITY, p));
1023 }
1024 
1025 void
1026 smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
1027     char *guid)
1028 {
1029 	if (domain)
1030 		(void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain,
1031 		    NETBIOS_NAME_SZ);
1032 
1033 	if (fqdn)
1034 		(void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn,
1035 		    MAXHOSTNAMELEN);
1036 
1037 	if (sid)
1038 		(void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid,
1039 		    SMB_SID_STRSZ);
1040 
1041 	if (forest)
1042 		(void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest,
1043 		    MAXHOSTNAMELEN);
1044 
1045 	if (guid)
1046 		(void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid,
1047 		    UUID_PRINTABLE_STRING_LENGTH);
1048 }
1049 
1050 void
1051 smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
1052     char *guid)
1053 {
1054 	if (domain)
1055 		(void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain);
1056 	if (fqdn)
1057 		(void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn);
1058 	if (sid)
1059 		(void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid);
1060 	if (forest)
1061 		(void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest);
1062 	if (guid)
1063 		(void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid);
1064 }
1065 
1066 /*
1067  * The version stored in SMF in string format as N.N where
1068  * N is a number defined by Microsoft. The first number represents
1069  * the major version and the second number is the minor version.
1070  * Current defined values can be found here in 'ver_table'.
1071  *
1072  * This function reads the SMF string value and converts it to
1073  * two numbers returned in the given 'version' structure.
1074  * Current default version number is 5.0 which is for Windows 2000.
1075  */
1076 void
1077 smb_config_get_version(smb_version_t *version)
1078 {
1079 	smb_version_t tmpver;
1080 	char verstr[SMB_VERSTR_LEN];
1081 	char *p;
1082 	int rc, i;
1083 	static smb_version_t ver_table [] = {
1084 		{ 0, SMB_MAJOR_NT,	SMB_MINOR_NT,		1381,	0 },
1085 		{ 0, SMB_MAJOR_2000,	SMB_MINOR_2000,		2195,	0 },
1086 		{ 0, SMB_MAJOR_XP,	SMB_MINOR_XP,		2196,	0 },
1087 		{ 0, SMB_MAJOR_2003,	SMB_MINOR_2003,		2196,	0 },
1088 		{ 0, SMB_MAJOR_VISTA,	SMB_MINOR_VISTA,	6000,	0 },
1089 		{ 0, SMB_MAJOR_2008,	SMB_MINOR_2008,		6000,	0 },
1090 		{ 0, SMB_MAJOR_2008R2,	SMB_MINOR_2008R2,	7007,	0 },
1091 		{ 0, SMB_MAJOR_7,	SMB_MINOR_7,		7007,	0 }
1092 	};
1093 
1094 	*version = ver_table[1];
1095 	version->sv_size = sizeof (smb_version_t);
1096 
1097 	rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr));
1098 	if (rc != SMBD_SMF_OK)
1099 		return;
1100 
1101 	if ((p = strchr(verstr, '.')) == NULL)
1102 		return;
1103 
1104 	*p = '\0';
1105 	tmpver.sv_major = (uint8_t)atoi(verstr);
1106 	tmpver.sv_minor = (uint8_t)atoi(p + 1);
1107 
1108 	for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) {
1109 		if ((tmpver.sv_major == ver_table[i].sv_major) &&
1110 		    (tmpver.sv_minor == ver_table[i].sv_minor)) {
1111 			*version = ver_table[i];
1112 			version->sv_size = sizeof (smb_version_t);
1113 			break;
1114 		}
1115 	}
1116 }
1117 
1118 /*
1119  * Reads share exec script properties
1120  */
1121 uint32_t
1122 smb_config_get_execinfo(char *map, char *unmap, size_t bufsz)
1123 {
1124 	char buf[MAXPATHLEN];
1125 	uint32_t flags = 0;
1126 
1127 	if (map == NULL) {
1128 		map = buf;
1129 		bufsz = MAXPATHLEN;
1130 	}
1131 
1132 	*map = '\0';
1133 	(void) smb_config_getstr(SMB_CI_MAP, map, bufsz);
1134 	if (*map != '\0')
1135 		flags |= SMB_EXEC_MAP;
1136 
1137 	if (unmap == NULL) {
1138 		unmap = buf;
1139 		bufsz = MAXPATHLEN;
1140 	}
1141 
1142 	*unmap = '\0';
1143 	(void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz);
1144 	if (*unmap != '\0')
1145 		flags |= SMB_EXEC_UNMAP;
1146 
1147 	*buf = '\0';
1148 	(void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
1149 	if (*buf != '\0')
1150 		if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1151 			flags |= SMB_EXEC_TERM;
1152 
1153 	return (flags);
1154 }
1155 
1156 static smb_cfg_param_t *
1157 smb_config_getent(smb_cfg_id_t id)
1158 {
1159 	int i;
1160 
1161 	for (i = 0; i < SMB_CI_MAX; i++)
1162 		if (smb_cfg_table[i].sc_id == id)
1163 			return (&smb_cfg_table[id]);
1164 
1165 	assert(0);
1166 	return (NULL);
1167 }
1168 
1169 /*
1170  * The service manifest has empty values by default for min_protocol and
1171  * max_protocol. The expectation is that when those values are empty, we don't
1172  * constrain the range of supported protocol versions (and allow use of the
1173  * whole range that we implement). For that reason, this should usually be the
1174  * highest protocol version we implement.
1175  */
1176 uint32_t max_protocol_default = SMB_VERS_3_0;
1177 
1178 uint32_t
1179 smb_config_get_max_protocol(void)
1180 {
1181 	char str[SMB_VERSTR_LEN];
1182 	int rc;
1183 	uint32_t max;
1184 
1185 	rc = smb_config_getstr(SMB_CI_MAX_PROTOCOL, str, sizeof (str));
1186 	if (rc == SMBD_SMF_OK) {
1187 		max = smb_convert_version_str(str);
1188 		if (max != 0)
1189 			return (max);
1190 		if (str[0] != '\0') {
1191 			syslog(LOG_ERR, "smbd/max_protocol value invalid");
1192 		}
1193 	}
1194 
1195 	return (max_protocol_default);
1196 }
1197 
1198 int
1199 smb_config_check_protocol(char *value)
1200 {
1201 	if (smb_convert_version_str(value) != 0)
1202 		return (0);
1203 
1204 	return (-1);
1205 }
1206 
1207 /*
1208  * If smb2_enable is present and max_protocol is empty,
1209  * set max_protocol.  Delete smb2_enable.
1210  */
1211 static void
1212 upgrade_smb2_enable()
1213 {
1214 	smb_scfhandle_t *handle;
1215 	char *s2e_name = "smb2_enable";
1216 	char *s2e_sval;
1217 	uint8_t	s2e_bval;
1218 	char *maxp_name = "max_protocol";
1219 	char *maxp_sval;
1220 	char verstr[SMB_VERSTR_LEN];
1221 	int rc;
1222 
1223 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
1224 	if (handle == NULL)
1225 		return;
1226 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
1227 	if (rc != SMBD_SMF_OK)
1228 		goto out;
1229 
1230 	/* Is there an "smb2_enable" property? */
1231 	rc = smb_smf_get_boolean_property(handle, s2e_name, &s2e_bval);
1232 	if (rc != SMBD_SMF_OK) {
1233 		syslog(LOG_DEBUG, "upgrade: smb2_enable not found");
1234 		goto out;
1235 	}
1236 
1237 	/*
1238 	 * We will try to delete the smb2_enable property, so we need
1239 	 * the transaction to start now, before we modify max_protocol
1240 	 */
1241 	if ((rc = smb_smf_start_transaction(handle)) != 0) {
1242 		syslog(LOG_DEBUG, "upgrade_smb2_enable: start trans (%d)", rc);
1243 		goto out;
1244 	}
1245 
1246 	/*
1247 	 * Old (smb2_enable) property exists.
1248 	 * Does the new one? (max_protocol)
1249 	 */
1250 	rc = smb_smf_get_string_property(handle, maxp_name,
1251 	    verstr, sizeof (verstr));
1252 	if (rc == SMBD_SMF_OK && !smb_config_check_protocol(verstr)) {
1253 		syslog(LOG_DEBUG, "upgrade: found %s = %s",
1254 		    maxp_name, verstr);
1255 		/* Leave existing max_protocol as we found it. */
1256 	} else {
1257 		/*
1258 		 * New property missing or invalid.
1259 		 * Upgrade from "smb2_enable".
1260 		 */
1261 		if (s2e_bval == 0) {
1262 			s2e_sval = "false";
1263 			maxp_sval = "1";
1264 		} else {
1265 			s2e_sval = "true";
1266 			maxp_sval = "2.1";
1267 		}
1268 		/*
1269 		 * Note: Need this in the same transaction as the
1270 		 * delete of smb2_enable below.
1271 		 */
1272 		rc = smb_smf_set_string_property(handle, maxp_name, maxp_sval);
1273 		if (rc != SMBD_SMF_OK) {
1274 			syslog(LOG_ERR, "failed to set smbd/%d (%d)",
1275 			    maxp_name, rc);
1276 			goto out;
1277 		}
1278 		syslog(LOG_INFO, "upgrade smbd/smb2_enable=%s "
1279 		    "converted to smbd/max_protocol=%s",
1280 		    s2e_sval, maxp_sval);
1281 	}
1282 
1283 	/*
1284 	 * Delete the old smb2_enable property.
1285 	 */
1286 	if ((rc = smb_smf_delete_property(handle, s2e_name)) != 0) {
1287 		syslog(LOG_DEBUG, "upgrade_smb2_enable: delete prop (%d)", rc);
1288 	} else if ((rc = smb_smf_end_transaction(handle)) != 0) {
1289 		syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1290 	}
1291 	if (rc != 0) {
1292 		syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1293 		    s2e_name, rc);
1294 	}
1295 
1296 out:
1297 	(void) smb_smf_end_transaction(handle);
1298 	smb_smf_scf_fini(handle);
1299 }
1300 
1301 
1302 /*
1303  * Run once at startup convert old SMF settings to current.
1304  */
1305 void
1306 smb_config_upgrade(void)
1307 {
1308 	upgrade_smb2_enable();
1309 }
1310 
1311 smb_cfg_val_t
1312 smb_config_get_require(smb_cfg_id_t id)
1313 {
1314 	int rc;
1315 	char str[sizeof ("required")];
1316 
1317 	rc = smb_config_getstr(id, str, sizeof (str));
1318 	if (rc != SMBD_SMF_OK)
1319 		return (SMB_CONFIG_DISABLED);
1320 
1321 	if (strncmp(str, "required", sizeof (str)) == 0)
1322 		return (SMB_CONFIG_REQUIRED);
1323 	if (strncmp(str, "enabled", sizeof (str)) == 0)
1324 		return (SMB_CONFIG_ENABLED);
1325 
1326 	return (SMB_CONFIG_DISABLED);
1327 }
1328