xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c (revision 13082:81ec56bf6147)
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_PRINT_ENABLE, "print_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_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0}
137  
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 *
smb_config_getname(smb_cfg_id_t id)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
smb_is_base64(unsigned char c)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 *
smb_base64_encode(char * str_to_encode)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 *
smb_base64_decode(char * encoded_str)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 *
smb_config_getenv_generic(char * name,char * svc_fmri_prefix,char * svc_propgrp)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
smb_config_setenv_generic(char * svc_fmri_prefix,char * svc_propgrp,char * name,char * value)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
smb_config_getstr(smb_cfg_id_t id,char * cbuf,int bufsz)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
smb_config_getip(smb_cfg_id_t sc_id,smb_inaddr_t * ipaddr)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
smb_config_getnum(smb_cfg_id_t id,int64_t * cint)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
smb_config_getbool(smb_cfg_id_t id)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
smb_config_get(smb_cfg_id_t id,char * cbuf,int bufsz)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
smb_config_setstr(smb_cfg_id_t id,char * value)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
smb_config_setnum(smb_cfg_id_t id,int64_t value)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
smb_config_setbool(smb_cfg_id_t id,boolean_t value)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
smb_config_set(smb_cfg_id_t id,char * value)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
smb_config_get_fg_flag()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_localsid
743   *
744   * Returns value of the "config/machine_sid" parameter
745   * from the IDMAP SMF configuration repository.
746   *
747   */
748  char *
smb_config_get_localsid(void)749  smb_config_get_localsid(void)
750  {
751  	return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX,
752  	    IDMAP_PG_NAME));
753  }
754  
755  /*
756   * smb_config_set_idmap_domain
757   *
758   * Set the "config/domain_name" parameter from IDMAP SMF repository.
759   */
760  int
smb_config_set_idmap_domain(char * value)761  smb_config_set_idmap_domain(char *value)
762  {
763  	return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
764  	    IDMAP_DOMAIN, value));
765  }
766  
767  /*
768   * smb_config_refresh_idmap
769   *
770   * Refresh IDMAP SMF service after making changes to its configuration.
771   */
772  int
smb_config_refresh_idmap(void)773  smb_config_refresh_idmap(void)
774  {
775  	char instance[32];
776  
777  	(void) snprintf(instance, sizeof (instance), "%s:default",
778  	    IDMAP_FMRI_PREFIX);
779  	return (smf_refresh_instance(instance));
780  }
781  
782  int
smb_config_secmode_fromstr(char * secmode)783  smb_config_secmode_fromstr(char *secmode)
784  {
785  	if (secmode == NULL)
786  		return (SMB_SECMODE_WORKGRP);
787  
788  	if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0)
789  		return (SMB_SECMODE_DOMAIN);
790  
791  	return (SMB_SECMODE_WORKGRP);
792  }
793  
794  char *
smb_config_secmode_tostr(int secmode)795  smb_config_secmode_tostr(int secmode)
796  {
797  	if (secmode == SMB_SECMODE_DOMAIN)
798  		return (SMB_SECMODE_DOMAIN_STR);
799  
800  	return (SMB_SECMODE_WORKGRP_STR);
801  }
802  
803  int
smb_config_get_secmode()804  smb_config_get_secmode()
805  {
806  	char p[16];
807  
808  	(void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p));
809  	return (smb_config_secmode_fromstr(p));
810  }
811  
812  int
smb_config_set_secmode(int secmode)813  smb_config_set_secmode(int secmode)
814  {
815  	char *p;
816  
817  	p = smb_config_secmode_tostr(secmode);
818  	return (smb_config_setstr(SMB_CI_SECURITY, p));
819  }
820  
821  void
smb_config_getdomaininfo(char * domain,char * fqdn,char * sid,char * forest,char * guid)822  smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
823      char *guid)
824  {
825  	if (domain)
826  		(void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain,
827  		    NETBIOS_NAME_SZ);
828  
829  	if (fqdn)
830  		(void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn,
831  		    MAXHOSTNAMELEN);
832  
833  	if (sid)
834  		(void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid,
835  		    SMB_SID_STRSZ);
836  
837  	if (forest)
838  		(void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest,
839  		    MAXHOSTNAMELEN);
840  
841  	if (guid)
842  		(void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid,
843  		    UUID_PRINTABLE_STRING_LENGTH);
844  }
845  
846  void
smb_config_setdomaininfo(char * domain,char * fqdn,char * sid,char * forest,char * guid)847  smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
848      char *guid)
849  {
850  	if (domain)
851  		(void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain);
852  	if (fqdn)
853  		(void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn);
854  	if (sid)
855  		(void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid);
856  	if (forest)
857  		(void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest);
858  	if (guid)
859  		(void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid);
860  }
861  
862  /*
863   * The version stored in SMF in string format as N.N where
864   * N is a number defined by Microsoft. The first number represents
865   * the major version and the second number is the minor version.
866   * Current defined values can be found here in 'ver_table'.
867   *
868   * This function reads the SMF string value and converts it to
869   * two numbers returned in the given 'version' structure.
870   * Current default version number is 5.0 which is for Windows 2000.
871   */
872  void
smb_config_get_version(smb_version_t * version)873  smb_config_get_version(smb_version_t *version)
874  {
875  	smb_version_t tmpver;
876  	char verstr[SMB_VERSTR_LEN];
877  	char *p;
878  	int rc, i;
879  	static smb_version_t ver_table [] = {
880  		{ 0, SMB_MAJOR_NT,	SMB_MINOR_NT,		1381,	0 },
881  		{ 0, SMB_MAJOR_2000,	SMB_MINOR_2000,		2195,	0 },
882  		{ 0, SMB_MAJOR_XP,	SMB_MINOR_XP,		2196,	0 },
883  		{ 0, SMB_MAJOR_2003,	SMB_MINOR_2003,		2196,	0 },
884  		{ 0, SMB_MAJOR_VISTA,	SMB_MINOR_VISTA,	6000,	0 },
885  		{ 0, SMB_MAJOR_2008,	SMB_MINOR_2008,		6000,	0 },
886  		{ 0, SMB_MAJOR_2008R2,	SMB_MINOR_2008R2,	7007,	0 },
887  		{ 0, SMB_MAJOR_7,	SMB_MINOR_7,		7007,	0 }
888  	};
889  
890  	*version = ver_table[1];
891  	version->sv_size = sizeof (smb_version_t);
892  
893  	rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr));
894  	if (rc != SMBD_SMF_OK)
895  		return;
896  
897  	if ((p = strchr(verstr, '.')) == NULL)
898  		return;
899  
900  	*p = '\0';
901  	tmpver.sv_major = (uint8_t)atoi(verstr);
902  	tmpver.sv_minor = (uint8_t)atoi(p + 1);
903  
904  	for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) {
905  		if ((tmpver.sv_major == ver_table[i].sv_major) &&
906  		    (tmpver.sv_minor == ver_table[i].sv_minor)) {
907  			*version = ver_table[i];
908  			version->sv_size = sizeof (smb_version_t);
909  			break;
910  		}
911  	}
912  }
913  
914  /*
915   * Reads share exec script properties
916   */
917  uint32_t
smb_config_get_execinfo(char * map,char * unmap,size_t bufsz)918  smb_config_get_execinfo(char *map, char *unmap, size_t bufsz)
919  {
920  	char buf[MAXPATHLEN];
921  	uint32_t flags = 0;
922  
923  	if (map == NULL) {
924  		map = buf;
925  		bufsz = MAXPATHLEN;
926  	}
927  
928  	*map = '\0';
929  	(void) smb_config_getstr(SMB_CI_MAP, map, bufsz);
930  	if (*map != '\0')
931  		flags |= SMB_EXEC_MAP;
932  
933  	if (unmap == NULL) {
934  		unmap = buf;
935  		bufsz = MAXPATHLEN;
936  	}
937  
938  	*unmap = '\0';
939  	(void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz);
940  	if (*unmap != '\0')
941  		flags |= SMB_EXEC_UNMAP;
942  
943  	*buf = '\0';
944  	(void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
945  	if (*buf != '\0')
946  		if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
947  			flags |= SMB_EXEC_TERM;
948  
949  	return (flags);
950  }
951  
952  static smb_cfg_param_t *
smb_config_getent(smb_cfg_id_t id)953  smb_config_getent(smb_cfg_id_t id)
954  {
955  	int i;
956  
957  	for (i = 0; i < SMB_CI_MAX; i++)
958  		if (smb_cfg_table[i].sc_id == id)
959  			return (&smb_cfg_table[id]);
960  
961  	assert(0);
962  	return (NULL);
963  }
964