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