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