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