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