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