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