xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c (revision b1d7ec75953cd517f5b7c3d9cb427ff8ec5d7d07)
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  */
24 
25 /*
26  * CIFS configuration management library
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <synch.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <syslog.h>
36 #include <netdb.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <libscf.h>
40 #include <assert.h>
41 #include <uuid/uuid.h>
42 #include <smbsrv/libsmb.h>
43 
44 typedef struct smb_cfg_param {
45 	smb_cfg_id_t sc_id;
46 	char *sc_name;
47 	int sc_type;
48 	uint32_t sc_flags;
49 } smb_cfg_param_t;
50 
51 /*
52  * config parameter flags
53  */
54 #define	SMB_CF_PROTECTED	0x01
55 #define	SMB_CF_EXEC		0x02
56 
57 /* idmap SMF fmri and Property Group */
58 #define	IDMAP_FMRI_PREFIX		"system/idmap"
59 #define	MACHINE_SID			"machine_sid"
60 #define	IDMAP_DOMAIN			"domain_name"
61 #define	IDMAP_PG_NAME			"config"
62 
63 #define	SMB_SECMODE_WORKGRP_STR 	"workgroup"
64 #define	SMB_SECMODE_DOMAIN_STR  	"domain"
65 
66 #define	SMB_ENC_LEN	1024
67 #define	SMB_DEC_LEN	256
68 
69 static char *b64_data =
70 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
71 
72 static smb_cfg_param_t smb_cfg_table[] =
73 {
74 	{SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
75 
76 	/* Oplock configuration, Kernel Only */
77 	{SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
78 
79 	/* Autohome configuration */
80 	{SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
81 
82 	/* Domain/PDC configuration */
83 	{SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0},
84 	{SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0},
85 	{SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0},
86 	{SMB_CI_DOMAIN_FQDN, "fqdn", SCF_TYPE_ASTRING, 0},
87 	{SMB_CI_DOMAIN_FOREST, "forest", SCF_TYPE_ASTRING, 0},
88 	{SMB_CI_DOMAIN_GUID, "domain_guid", SCF_TYPE_ASTRING, 0},
89 	{SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0},
90 
91 	/* WINS configuration */
92 	{SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0},
93 	{SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0},
94 	{SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0},
95 
96 	/* Kmod specific configuration */
97 	{SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0},
98 	{SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0},
99 	{SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0},
100 	{SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0},
101 
102 	{SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0},
103 	{SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0},
104 
105 	/* Kmod tuning configuration */
106 	{SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0},
107 
108 	/* SMBd configuration */
109 	{SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0},
110 	{SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0},
111 	{SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0},
112 	{SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0},
113 
114 	/* ADS Configuration */
115 	{SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0},
116 
117 	/* Dynamic DNS */
118 	{SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0},
119 
120 	{SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
121 	    SMB_CF_PROTECTED},
122 	{SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING,
123 	    0},
124 	{SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING,
125 	    0},
126 	{SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER,
127 	    0},
128 	{SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER,
129 	    0},
130 	{SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
131 	{SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
132 	{SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
133 	{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
134 
135 	{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0}
136 
137 	/* SMB_CI_MAX */
138 };
139 
140 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
141 
142 static boolean_t smb_is_base64(unsigned char c);
143 static char *smb_base64_encode(char *str_to_encode);
144 static char *smb_base64_decode(char *encoded_str);
145 
146 char *
147 smb_config_getname(smb_cfg_id_t id)
148 {
149 	smb_cfg_param_t *cfg;
150 	cfg = smb_config_getent(id);
151 	return (cfg->sc_name);
152 }
153 
154 static boolean_t
155 smb_is_base64(unsigned char c)
156 {
157 	return (isalnum(c) || (c == '+') || (c == '/'));
158 }
159 
160 /*
161  * smb_base64_encode
162  *
163  * Encode a string using base64 algorithm.
164  * Caller should free the returned buffer when done.
165  */
166 static char *
167 smb_base64_encode(char *str_to_encode)
168 {
169 	int ret_cnt = 0;
170 	int i = 0, j = 0;
171 	char arr_3[3], arr_4[4];
172 	int len = strlen(str_to_encode);
173 	char *ret = malloc(SMB_ENC_LEN);
174 
175 	if (ret == NULL) {
176 		return (NULL);
177 	}
178 
179 	while (len--) {
180 		arr_3[i++] = *(str_to_encode++);
181 		if (i == 3) {
182 			arr_4[0] = (arr_3[0] & 0xfc) >> 2;
183 			arr_4[1] = ((arr_3[0] & 0x03) << 4) +
184 			    ((arr_3[1] & 0xf0) >> 4);
185 			arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
186 			    ((arr_3[2] & 0xc0) >> 6);
187 			arr_4[3] = arr_3[2] & 0x3f;
188 
189 			for (i = 0; i < 4; i++)
190 				ret[ret_cnt++] = b64_data[arr_4[i]];
191 			i = 0;
192 		}
193 	}
194 
195 	if (i) {
196 		for (j = i; j < 3; j++)
197 			arr_3[j] = '\0';
198 
199 		arr_4[0] = (arr_3[0] & 0xfc) >> 2;
200 		arr_4[1] = ((arr_3[0] & 0x03) << 4) +
201 		    ((arr_3[1] & 0xf0) >> 4);
202 		arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
203 		    ((arr_3[2] & 0xc0) >> 6);
204 		arr_4[3] = arr_3[2] & 0x3f;
205 
206 		for (j = 0; j < (i + 1); j++)
207 			ret[ret_cnt++] = b64_data[arr_4[j]];
208 
209 		while (i++ < 3)
210 			ret[ret_cnt++] = '=';
211 	}
212 
213 	ret[ret_cnt++] = '\0';
214 	return (ret);
215 }
216 
217 /*
218  * smb_base64_decode
219  *
220  * Decode using base64 algorithm.
221  * Caller should free the returned buffer when done.
222  */
223 static char *
224 smb_base64_decode(char *encoded_str)
225 {
226 	int len = strlen(encoded_str);
227 	int i = 0, j = 0;
228 	int en_ind = 0;
229 	char arr_4[4], arr_3[3];
230 	int ret_cnt = 0;
231 	char *ret = malloc(SMB_DEC_LEN);
232 	char *p;
233 
234 	if (ret == NULL) {
235 		return (NULL);
236 	}
237 
238 	while (len-- && (encoded_str[en_ind] != '=') &&
239 	    smb_is_base64(encoded_str[en_ind])) {
240 		arr_4[i++] = encoded_str[en_ind];
241 		en_ind++;
242 		if (i == 4) {
243 			for (i = 0; i < 4; i++) {
244 				if ((p = strchr(b64_data, arr_4[i])) == NULL)
245 					return (NULL);
246 
247 				arr_4[i] = (int)(p - b64_data);
248 			}
249 
250 			arr_3[0] = (arr_4[0] << 2) +
251 			    ((arr_4[1] & 0x30) >> 4);
252 			arr_3[1] = ((arr_4[1] & 0xf) << 4) +
253 			    ((arr_4[2] & 0x3c) >> 2);
254 			arr_3[2] = ((arr_4[2] & 0x3) << 6) +
255 			    arr_4[3];
256 
257 			for (i = 0; i < 3; i++)
258 				ret[ret_cnt++] = arr_3[i];
259 
260 			i = 0;
261 		}
262 	}
263 
264 	if (i) {
265 		for (j = i; j < 4; j++)
266 			arr_4[j] = 0;
267 
268 		for (j = 0; j < 4; j++) {
269 			if ((p = strchr(b64_data, arr_4[j])) == NULL)
270 				return (NULL);
271 
272 			arr_4[j] = (int)(p - b64_data);
273 		}
274 		arr_3[0] = (arr_4[0] << 2) +
275 		    ((arr_4[1] & 0x30) >> 4);
276 		arr_3[1] = ((arr_4[1] & 0xf) << 4) +
277 		    ((arr_4[2] & 0x3c) >> 2);
278 		arr_3[2] = ((arr_4[2] & 0x3) << 6) +
279 		    arr_4[3];
280 		for (j = 0; j < (i - 1); j++)
281 			ret[ret_cnt++] = arr_3[j];
282 	}
283 
284 	ret[ret_cnt++] = '\0';
285 	return (ret);
286 }
287 
288 static char *
289 smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp)
290 {
291 	smb_scfhandle_t *handle;
292 	char *value;
293 
294 	if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL)
295 		return (NULL);
296 
297 	handle = smb_smf_scf_init(svc_fmri_prefix);
298 	if (handle == NULL) {
299 		free(value);
300 		return (NULL);
301 	}
302 
303 	(void) smb_smf_create_service_pgroup(handle, svc_propgrp);
304 
305 	if (smb_smf_get_string_property(handle, name, value,
306 	    sizeof (char) * MAX_VALUE_BUFLEN) != 0) {
307 		smb_smf_scf_fini(handle);
308 		free(value);
309 		return (NULL);
310 	}
311 
312 	smb_smf_scf_fini(handle);
313 	return (value);
314 
315 }
316 
317 static int
318 smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp,
319     char *name, char *value)
320 {
321 	smb_scfhandle_t *handle = NULL;
322 	int rc = 0;
323 
324 
325 	handle = smb_smf_scf_init(svc_fmri_prefix);
326 	if (handle == NULL) {
327 		return (1);
328 	}
329 
330 	(void) smb_smf_create_service_pgroup(handle, svc_propgrp);
331 
332 	if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) {
333 		smb_smf_scf_fini(handle);
334 		return (1);
335 	}
336 
337 	if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK)
338 		rc = 1;
339 
340 	if (smb_smf_end_transaction(handle) != SMBD_SMF_OK)
341 		rc = 1;
342 
343 	smb_smf_scf_fini(handle);
344 	return (rc);
345 }
346 
347 /*
348  * smb_config_getstr
349  *
350  * Fetch the specified string configuration item from SMF
351  */
352 int
353 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
354 {
355 	smb_scfhandle_t *handle;
356 	smb_cfg_param_t *cfg;
357 	int rc = SMBD_SMF_OK;
358 	char *pg;
359 	char protbuf[SMB_ENC_LEN];
360 	char *tmp;
361 
362 	*cbuf = '\0';
363 	cfg = smb_config_getent(id);
364 	assert(cfg->sc_type == SCF_TYPE_ASTRING);
365 
366 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
367 	if (handle == NULL)
368 		return (SMBD_SMF_SYSTEM_ERR);
369 
370 	if (cfg->sc_flags & SMB_CF_PROTECTED) {
371 		if ((rc = smb_smf_create_service_pgroup(handle,
372 		    SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
373 			goto error;
374 
375 		if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
376 		    protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
377 			goto error;
378 
379 		if (*protbuf != '\0') {
380 			tmp = smb_base64_decode(protbuf);
381 			(void) strlcpy(cbuf, tmp, bufsz);
382 			free(tmp);
383 		}
384 	} else {
385 		pg = (cfg->sc_flags & SMB_CF_EXEC) ? SMBD_EXEC_PG_NAME :
386 		    SMBD_PG_NAME;
387 		rc = smb_smf_create_service_pgroup(handle, pg);
388 		if (rc == SMBD_SMF_OK)
389 			rc = smb_smf_get_string_property(handle, cfg->sc_name,
390 			    cbuf, bufsz);
391 	}
392 
393 error:
394 	smb_smf_scf_fini(handle);
395 	return (rc);
396 }
397 
398 /*
399  * Translate the value of an astring SMF property into a binary
400  * IP address. If the value is neither a valid IPv4 nor IPv6
401  * address, attempt to look it up as a hostname using the
402  * configured address type.
403  */
404 int
405 smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr)
406 {
407 	int rc, error;
408 	int a_family;
409 	char ipstr[MAXHOSTNAMELEN];
410 	struct hostent *h;
411 	smb_cfg_param_t *cfg;
412 
413 	if (ipaddr == NULL)
414 		return (SMBD_SMF_INVALID_ARG);
415 
416 	bzero(ipaddr, sizeof (smb_inaddr_t));
417 	rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr));
418 	if (rc == SMBD_SMF_OK) {
419 		if (*ipstr == '\0')
420 			return (SMBD_SMF_INVALID_ARG);
421 
422 		if (inet_pton(AF_INET, ipstr, &ipaddr->a_ipv4) == 1) {
423 			ipaddr->a_family = AF_INET;
424 			return (SMBD_SMF_OK);
425 		}
426 
427 		if (inet_pton(AF_INET6, ipstr, &ipaddr->a_ipv6) == 1) {
428 			ipaddr->a_family = AF_INET6;
429 			return (SMBD_SMF_OK);
430 		}
431 
432 		/*
433 		 * The value is neither an IPv4 nor IPv6 address;
434 		 * so check if it's a hostname.
435 		 */
436 		a_family = smb_config_getbool(SMB_CI_IPV6_ENABLE) ?
437 		    AF_INET6 : AF_INET;
438 		h = getipnodebyname(ipstr, a_family, AI_DEFAULT,
439 		    &error);
440 		if (h != NULL) {
441 			bcopy(*(h->h_addr_list), &ipaddr->a_ip,
442 			    h->h_length);
443 			ipaddr->a_family = a_family;
444 			freehostent(h);
445 			rc = SMBD_SMF_OK;
446 		} else {
447 			cfg = smb_config_getent(sc_id);
448 			syslog(LOG_ERR, "smbd/%s: %s unable to get %s "
449 			    "address: %d", cfg->sc_name, ipstr,
450 			    a_family == AF_INET ?  "IPv4" : "IPv6", error);
451 			rc = SMBD_SMF_INVALID_ARG;
452 		}
453 	}
454 
455 	return (rc);
456 }
457 
458 /*
459  * smb_config_getnum
460  *
461  * Returns the value of a numeric config param.
462  */
463 int
464 smb_config_getnum(smb_cfg_id_t id, int64_t *cint)
465 {
466 	smb_scfhandle_t *handle;
467 	smb_cfg_param_t *cfg;
468 	int rc = SMBD_SMF_OK;
469 
470 	*cint = 0;
471 	cfg = smb_config_getent(id);
472 	assert(cfg->sc_type == SCF_TYPE_INTEGER);
473 
474 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
475 	if (handle == NULL)
476 		return (SMBD_SMF_SYSTEM_ERR);
477 
478 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
479 	if (rc == SMBD_SMF_OK)
480 		rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint);
481 	smb_smf_scf_fini(handle);
482 
483 	return (rc);
484 }
485 
486 /*
487  * smb_config_getbool
488  *
489  * Returns the value of a boolean config param.
490  */
491 boolean_t
492 smb_config_getbool(smb_cfg_id_t id)
493 {
494 	smb_scfhandle_t *handle;
495 	smb_cfg_param_t *cfg;
496 	int rc = SMBD_SMF_OK;
497 	uint8_t vbool;
498 
499 	cfg = smb_config_getent(id);
500 	assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
501 
502 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
503 	if (handle == NULL)
504 		return (B_FALSE);
505 
506 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
507 	if (rc == SMBD_SMF_OK)
508 		rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool);
509 	smb_smf_scf_fini(handle);
510 
511 	return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE);
512 }
513 
514 /*
515  * smb_config_get
516  *
517  * This function returns the value of the requested config
518  * iterm regardless of its type in string format. This should
519  * be used when the config item type is not known by the caller.
520  */
521 int
522 smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz)
523 {
524 	smb_cfg_param_t *cfg;
525 	int64_t cint;
526 	int rc;
527 
528 	cfg = smb_config_getent(id);
529 	switch (cfg->sc_type) {
530 	case SCF_TYPE_ASTRING:
531 		return (smb_config_getstr(id, cbuf, bufsz));
532 
533 	case SCF_TYPE_INTEGER:
534 		rc = smb_config_getnum(id, &cint);
535 		if (rc == SMBD_SMF_OK)
536 			(void) snprintf(cbuf, bufsz, "%lld", cint);
537 		return (rc);
538 
539 	case SCF_TYPE_BOOLEAN:
540 		if (smb_config_getbool(id))
541 			(void) strlcpy(cbuf, "true", bufsz);
542 		else
543 			(void) strlcpy(cbuf, "false", bufsz);
544 		return (SMBD_SMF_OK);
545 	}
546 
547 	return (SMBD_SMF_INVALID_ARG);
548 }
549 
550 /*
551  * smb_config_setstr
552  *
553  * Set the specified config param with the given
554  * value.
555  */
556 int
557 smb_config_setstr(smb_cfg_id_t id, char *value)
558 {
559 	smb_scfhandle_t *handle;
560 	smb_cfg_param_t *cfg;
561 	int rc = SMBD_SMF_OK;
562 	boolean_t protected;
563 	char *tmp = NULL;
564 	char *pg;
565 
566 	cfg = smb_config_getent(id);
567 	assert(cfg->sc_type == SCF_TYPE_ASTRING);
568 
569 	protected = B_FALSE;
570 
571 	switch (cfg->sc_flags) {
572 	case SMB_CF_PROTECTED:
573 		protected = B_TRUE;
574 		pg = SMBD_PROTECTED_PG_NAME;
575 		break;
576 	case SMB_CF_EXEC:
577 		pg = SMBD_EXEC_PG_NAME;
578 		break;
579 	default:
580 		pg = SMBD_PG_NAME;
581 		break;
582 	}
583 
584 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
585 	if (handle == NULL)
586 		return (SMBD_SMF_SYSTEM_ERR);
587 
588 	rc = smb_smf_create_service_pgroup(handle, pg);
589 	if (rc == SMBD_SMF_OK)
590 		rc = smb_smf_start_transaction(handle);
591 
592 	if (rc != SMBD_SMF_OK) {
593 		smb_smf_scf_fini(handle);
594 		return (rc);
595 	}
596 
597 	if (protected && value && (*value != '\0')) {
598 		if ((tmp = smb_base64_encode(value)) == NULL) {
599 			(void) smb_smf_end_transaction(handle);
600 			smb_smf_scf_fini(handle);
601 			return (SMBD_SMF_NO_MEMORY);
602 		}
603 
604 		value = tmp;
605 	}
606 
607 	rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
608 
609 	free(tmp);
610 	(void) smb_smf_end_transaction(handle);
611 	smb_smf_scf_fini(handle);
612 	return (rc);
613 }
614 
615 /*
616  * smb_config_setnum
617  *
618  * Sets a numeric configuration iterm
619  */
620 int
621 smb_config_setnum(smb_cfg_id_t id, int64_t value)
622 {
623 	smb_scfhandle_t *handle;
624 	smb_cfg_param_t *cfg;
625 	int rc = SMBD_SMF_OK;
626 
627 	cfg = smb_config_getent(id);
628 	assert(cfg->sc_type == SCF_TYPE_INTEGER);
629 
630 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
631 	if (handle == NULL)
632 		return (SMBD_SMF_SYSTEM_ERR);
633 
634 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
635 	if (rc == SMBD_SMF_OK)
636 		rc = smb_smf_start_transaction(handle);
637 
638 	if (rc != SMBD_SMF_OK) {
639 		smb_smf_scf_fini(handle);
640 		return (rc);
641 	}
642 
643 	rc = smb_smf_set_integer_property(handle, cfg->sc_name, value);
644 
645 	(void) smb_smf_end_transaction(handle);
646 	smb_smf_scf_fini(handle);
647 	return (rc);
648 }
649 
650 /*
651  * smb_config_setbool
652  *
653  * Sets a boolean configuration iterm
654  */
655 int
656 smb_config_setbool(smb_cfg_id_t id, boolean_t value)
657 {
658 	smb_scfhandle_t *handle;
659 	smb_cfg_param_t *cfg;
660 	int rc = SMBD_SMF_OK;
661 
662 	cfg = smb_config_getent(id);
663 	assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
664 
665 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
666 	if (handle == NULL)
667 		return (SMBD_SMF_SYSTEM_ERR);
668 
669 	rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
670 	if (rc == SMBD_SMF_OK)
671 		rc = smb_smf_start_transaction(handle);
672 
673 	if (rc != SMBD_SMF_OK) {
674 		smb_smf_scf_fini(handle);
675 		return (rc);
676 	}
677 
678 	rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value);
679 
680 	(void) smb_smf_end_transaction(handle);
681 	smb_smf_scf_fini(handle);
682 	return (rc);
683 }
684 
685 /*
686  * smb_config_set
687  *
688  * This function sets the value of the specified config
689  * iterm regardless of its type in string format. This should
690  * be used when the config item type is not known by the caller.
691  */
692 int
693 smb_config_set(smb_cfg_id_t id, char *value)
694 {
695 	smb_cfg_param_t *cfg;
696 	int64_t cint;
697 
698 	cfg = smb_config_getent(id);
699 	switch (cfg->sc_type) {
700 	case SCF_TYPE_ASTRING:
701 		return (smb_config_setstr(id, value));
702 
703 	case SCF_TYPE_INTEGER:
704 		cint = atoi(value);
705 		return (smb_config_setnum(id, cint));
706 
707 	case SCF_TYPE_BOOLEAN:
708 		return (smb_config_setbool(id, strcasecmp(value, "true") == 0));
709 	}
710 
711 	return (SMBD_SMF_INVALID_ARG);
712 }
713 uint8_t
714 smb_config_get_fg_flag()
715 {
716 	uint8_t run_fg = 0; /* Default is to run in daemon mode */
717 	smb_scfhandle_t *handle = NULL;
718 
719 	handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
720 	if (handle == NULL) {
721 		return (run_fg);
722 	}
723 
724 	if (smb_smf_create_service_pgroup(handle,
725 	    SMBD_PG_NAME) != SMBD_SMF_OK) {
726 		smb_smf_scf_fini(handle);
727 		return (run_fg);
728 	}
729 
730 	if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) {
731 		smb_smf_scf_fini(handle);
732 		return (run_fg);
733 	}
734 
735 	smb_smf_scf_fini(handle);
736 
737 	return (run_fg);
738 }
739 
740 /*
741  * smb_config_get_localsid
742  *
743  * Returns value of the "config/machine_sid" parameter
744  * from the IDMAP SMF configuration repository.
745  *
746  */
747 char *
748 smb_config_get_localsid(void)
749 {
750 	return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX,
751 	    IDMAP_PG_NAME));
752 }
753 
754 /*
755  * smb_config_set_idmap_domain
756  *
757  * Set the "config/domain_name" parameter from IDMAP SMF repository.
758  */
759 int
760 smb_config_set_idmap_domain(char *value)
761 {
762 	return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
763 	    IDMAP_DOMAIN, value));
764 }
765 
766 /*
767  * smb_config_refresh_idmap
768  *
769  * Refresh IDMAP SMF service after making changes to its configuration.
770  */
771 int
772 smb_config_refresh_idmap(void)
773 {
774 	char instance[32];
775 
776 	(void) snprintf(instance, sizeof (instance), "%s:default",
777 	    IDMAP_FMRI_PREFIX);
778 	return (smf_refresh_instance(instance));
779 }
780 
781 int
782 smb_config_secmode_fromstr(char *secmode)
783 {
784 	if (secmode == NULL)
785 		return (SMB_SECMODE_WORKGRP);
786 
787 	if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0)
788 		return (SMB_SECMODE_DOMAIN);
789 
790 	return (SMB_SECMODE_WORKGRP);
791 }
792 
793 char *
794 smb_config_secmode_tostr(int secmode)
795 {
796 	if (secmode == SMB_SECMODE_DOMAIN)
797 		return (SMB_SECMODE_DOMAIN_STR);
798 
799 	return (SMB_SECMODE_WORKGRP_STR);
800 }
801 
802 int
803 smb_config_get_secmode()
804 {
805 	char p[16];
806 
807 	(void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p));
808 	return (smb_config_secmode_fromstr(p));
809 }
810 
811 int
812 smb_config_set_secmode(int secmode)
813 {
814 	char *p;
815 
816 	p = smb_config_secmode_tostr(secmode);
817 	return (smb_config_setstr(SMB_CI_SECURITY, p));
818 }
819 
820 void
821 smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
822     char *guid)
823 {
824 	if (domain)
825 		(void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain,
826 		    NETBIOS_NAME_SZ);
827 
828 	if (fqdn)
829 		(void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn,
830 		    MAXHOSTNAMELEN);
831 
832 	if (sid)
833 		(void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid,
834 		    SMB_SID_STRSZ);
835 
836 	if (forest)
837 		(void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest,
838 		    MAXHOSTNAMELEN);
839 
840 	if (guid)
841 		(void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid,
842 		    UUID_PRINTABLE_STRING_LENGTH);
843 }
844 
845 void
846 smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
847     char *guid)
848 {
849 	if (domain)
850 		(void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain);
851 	if (fqdn)
852 		(void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn);
853 	if (sid)
854 		(void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid);
855 	if (forest)
856 		(void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest);
857 	if (guid)
858 		(void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid);
859 }
860 
861 /*
862  * The version stored in SMF in string format as N.N where
863  * N is a number defined by Microsoft. The first number represents
864  * the major version and the second number is the minor version.
865  * Current defined values can be found here in 'ver_table'.
866  *
867  * This function reads the SMF string value and converts it to
868  * two numbers returned in the given 'version' structure.
869  * Current default version number is 5.0 which is for Windows 2000.
870  */
871 void
872 smb_config_get_version(smb_version_t *version)
873 {
874 	smb_version_t tmpver;
875 	char verstr[SMB_VERSTR_LEN];
876 	char *p;
877 	int rc, i;
878 	static smb_version_t ver_table [] = {
879 		{ SMB_MAJOR_NT,		SMB_MINOR_NT	},
880 		{ SMB_MAJOR_2000,	SMB_MINOR_2000	},
881 		{ SMB_MAJOR_XP,		SMB_MINOR_XP	},
882 		{ SMB_MAJOR_2003,	SMB_MINOR_2003	},
883 		{ SMB_MAJOR_VISTA,	SMB_MINOR_VISTA	},
884 		{ SMB_MAJOR_2008,	SMB_MINOR_2008	},
885 		{ SMB_MAJOR_2008R2,	SMB_MINOR_2008R2}
886 	};
887 
888 	*version = ver_table[1];
889 
890 	rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr));
891 	if (rc != SMBD_SMF_OK)
892 		return;
893 
894 	if ((p = strchr(verstr, '.')) == NULL)
895 		return;
896 
897 	*p = '\0';
898 	tmpver.sv_major = (uint8_t)atoi(verstr);
899 	tmpver.sv_minor = (uint8_t)atoi(p + 1);
900 
901 	for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) {
902 		if ((tmpver.sv_major == ver_table[i].sv_major) &&
903 		    (tmpver.sv_minor == ver_table[i].sv_minor)) {
904 			*version = ver_table[i];
905 			break;
906 		}
907 	}
908 }
909 
910 /*
911  * Reads share exec script properties
912  */
913 uint32_t
914 smb_config_get_execinfo(char *map, char *unmap, size_t bufsz)
915 {
916 	char buf[MAXPATHLEN];
917 	uint32_t flags = 0;
918 
919 	if (map == NULL) {
920 		map = buf;
921 		bufsz = MAXPATHLEN;
922 	}
923 
924 	*map = '\0';
925 	(void) smb_config_getstr(SMB_CI_MAP, map, bufsz);
926 	if (*map != '\0')
927 		flags |= SMB_EXEC_MAP;
928 
929 	if (unmap == NULL) {
930 		unmap = buf;
931 		bufsz = MAXPATHLEN;
932 	}
933 
934 	*unmap = '\0';
935 	(void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz);
936 	if (*unmap != '\0')
937 		flags |= SMB_EXEC_UNMAP;
938 
939 	*buf = '\0';
940 	(void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
941 	if (*buf != '\0')
942 		if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
943 			flags |= SMB_EXEC_TERM;
944 
945 	return (flags);
946 }
947 
948 static smb_cfg_param_t *
949 smb_config_getent(smb_cfg_id_t id)
950 {
951 	int i;
952 
953 	for (i = 0; i < SMB_CI_MAX; i++)
954 		if (smb_cfg_table[i].sc_id == id)
955 			return (&smb_cfg_table[id]);
956 
957 	assert(0);
958 	return (NULL);
959 }
960