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