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 2018 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2020 RackTop Systems, Inc.
25 */
26
27 /*
28 * CIFS configuration management library
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <synch.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <syslog.h>
38 #include <netdb.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 #include <libscf.h>
42 #include <assert.h>
43 #include <uuid/uuid.h>
44 #include <smbsrv/libsmb.h>
45
46 typedef struct smb_cfg_param {
47 smb_cfg_id_t sc_id;
48 char *sc_name;
49 int sc_type;
50 uint32_t sc_flags;
51 } smb_cfg_param_t;
52
53 struct str_val {
54 char *str;
55 uint32_t val;
56 };
57
58 /*
59 * config parameter flags
60 */
61 #define SMB_CF_PROTECTED 0x01
62 #define SMB_CF_EXEC 0x02
63
64 /* idmap SMF fmri and Property Group */
65 #define IDMAP_FMRI_PREFIX "system/idmap"
66 #define MACHINE_SID "machine_sid"
67 #define MACHINE_UUID "machine_uuid"
68 #define IDMAP_DOMAIN "domain_name"
69 #define IDMAP_PREF_DC "preferred_dc"
70 #define IDMAP_SITE_NAME "site_name"
71 #define IDMAP_PG_NAME "config"
72
73 #define SMB_SECMODE_WORKGRP_STR "workgroup"
74 #define SMB_SECMODE_DOMAIN_STR "domain"
75
76 #define SMB_ENC_LEN 1024
77 #define SMB_DEC_LEN 256
78
79 static char *b64_data =
80 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
81
82 static smb_cfg_param_t smb_cfg_table[] =
83 {
84 {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
85
86 /* Oplock configuration, Kernel Only */
87 {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
88
89 /* Autohome configuration */
90 {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
91
92 /* Domain/PDC configuration */
93 {SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0},
94 {SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0},
95 {SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0},
96 {SMB_CI_DOMAIN_FQDN, "fqdn", SCF_TYPE_ASTRING, 0},
97 {SMB_CI_DOMAIN_FOREST, "forest", SCF_TYPE_ASTRING, 0},
98 {SMB_CI_DOMAIN_GUID, "domain_guid", SCF_TYPE_ASTRING, 0},
99 {SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0},
100
101 /* WINS configuration */
102 {SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0},
103 {SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0},
104 {SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0},
105
106 /* Kmod specific configuration */
107 {SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0},
108 {SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0},
109 {SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0},
110 {SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0},
111
112 {SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0},
113 {SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0},
114
115 /* Kmod tuning configuration */
116 {SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0},
117
118 /* SMBd configuration */
119 {SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0},
120 {SMB_CI_NETBIOS_ENABLE, "netbios_enable", SCF_TYPE_BOOLEAN, 0},
121 {SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0},
122 {SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0},
123 {SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0},
124
125 /* ADS Configuration */
126 {SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0},
127
128 /* Dynamic DNS */
129 {SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0},
130
131 {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
132 SMB_CF_PROTECTED},
133
134 {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
135 {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
136 {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
137 {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
138 {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
139 {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
140 {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
141 {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
142 {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
143 {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
144 {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
145 {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
146 {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
147 {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
148 {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
149 {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},
150 {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0},
151 {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0},
152 {SMB_CI_BYPASS_TRAVERSE_CHECKING,
153 "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0},
154 {SMB_CI_ENCRYPT_CIPHER, "encrypt_cipher", SCF_TYPE_ASTRING, 0},
155
156 /* SMB_CI_MAX */
157 };
158
159 /*
160 * We store the max SMB protocol version in SMF as a string,
161 * (for convenience of svccfg etc) but the programmatic get/set
162 * interfaces use the numeric form.
163 *
164 * The numeric values are as defined in the [MS-SMB2] spec.
165 * except for how we represent "1" (for SMB1) which is an
166 * arbitrary value below SMB2_VERS_BASE.
167 */
168 static struct str_val
169 smb_versions[] = {
170 { "3.11", SMB_VERS_3_11 },
171 { "3.02", SMB_VERS_3_02 },
172 { "3.0", SMB_VERS_3_0 },
173 { "2.1", SMB_VERS_2_1 },
174 { "2.002", SMB_VERS_2_002 },
175 { "1", SMB_VERS_1 },
176 { NULL, 0 }
177 };
178
179 /*
180 * Supported encryption ciphers.
181 */
182 static struct str_val
183 smb31_encrypt_ciphers[] = {
184 { "aes128-ccm", SMB3_CIPHER_AES128_CCM }, /* SMB 3.x */
185 { "aes128-gcm", SMB3_CIPHER_AES128_GCM }, /* SMB 3.1.1 */
186 { NULL, 0 }
187 };
188
189 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
190
191 static boolean_t smb_is_base64(unsigned char c);
192 static char *smb_base64_encode(char *str_to_encode);
193 static char *smb_base64_decode(char *encoded_str);
194 static int smb_config_get_idmap_preferred_dc(char *, int);
195 static int smb_config_set_idmap_preferred_dc(char *);
196 static int smb_config_get_idmap_site_name(char *, int);
197 static int smb_config_set_idmap_site_name(char *);
198
199 static uint32_t
200 smb_convert_version_str(const char *version)
201 {
202 uint32_t dialect = 0;
203 int i;
204
205 for (i = 0; smb_versions[i].str != NULL; i++) {
206 if (strcmp(version, smb_versions[i].str) == 0)
207 dialect = smb_versions[i].val;
208 }
209
210 return (dialect);
211 }
212
213 char *
214 smb_config_getname(smb_cfg_id_t id)
215 {
216 smb_cfg_param_t *cfg;
217 cfg = smb_config_getent(id);
218 return (cfg->sc_name);
219 }
220
221 static boolean_t
222 smb_is_base64(unsigned char c)
223 {
224 return (isalnum(c) || (c == '+') || (c == '/'));
225 }
226
227 /*
228 * smb_base64_encode
229 *
230 * Encode a string using base64 algorithm.
231 * Caller should free the returned buffer when done.
232 */
233 static char *
234 smb_base64_encode(char *str_to_encode)
235 {
236 int ret_cnt = 0;
237 int i = 0, j = 0;
238 char arr_3[3], arr_4[4];
239 int len = strlen(str_to_encode);
240 char *ret = malloc(SMB_ENC_LEN);
241
242 if (ret == NULL) {
243 return (NULL);
244 }
245
246 while (len--) {
247 arr_3[i++] = *(str_to_encode++);
248 if (i == 3) {
249 arr_4[0] = (arr_3[0] & 0xfc) >> 2;
250 arr_4[1] = ((arr_3[0] & 0x03) << 4) +
251 ((arr_3[1] & 0xf0) >> 4);
252 arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
253 ((arr_3[2] & 0xc0) >> 6);
254 arr_4[3] = arr_3[2] & 0x3f;
255
256 for (i = 0; i < 4; i++)
257 ret[ret_cnt++] = b64_data[arr_4[i]];
258 i = 0;
259 }
260 }
261
262 if (i) {
263 for (j = i; j < 3; j++)
264 arr_3[j] = '\0';
265
266 arr_4[0] = (arr_3[0] & 0xfc) >> 2;
267 arr_4[1] = ((arr_3[0] & 0x03) << 4) +
268 ((arr_3[1] & 0xf0) >> 4);
269 arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
270 ((arr_3[2] & 0xc0) >> 6);
271 arr_4[3] = arr_3[2] & 0x3f;
272
273 for (j = 0; j < (i + 1); j++)
274 ret[ret_cnt++] = b64_data[arr_4[j]];
275
276 while (i++ < 3)
277 ret[ret_cnt++] = '=';
278 }
279
280 ret[ret_cnt++] = '\0';
281 return (ret);
282 }
283
284 /*
285 * smb_base64_decode
286 *
287 * Decode using base64 algorithm.
288 * Caller should free the returned buffer when done.
289 */
290 static char *
291 smb_base64_decode(char *encoded_str)
292 {
293 int len = strlen(encoded_str);
294 int i = 0, j = 0;
295 int en_ind = 0;
296 char arr_4[4], arr_3[3];
297 int ret_cnt = 0;
298 char *ret = malloc(SMB_DEC_LEN);
299 char *p;
300
301 if (ret == NULL) {
302 return (NULL);
303 }
304
305 while (len-- && (encoded_str[en_ind] != '=') &&
306 smb_is_base64(encoded_str[en_ind])) {
307 arr_4[i++] = encoded_str[en_ind];
308 en_ind++;
309 if (i == 4) {
310 for (i = 0; i < 4; i++) {
311 if ((p = strchr(b64_data, arr_4[i])) == NULL)
312 return (NULL);
313
314 arr_4[i] = (int)(p - b64_data);
315 }
316
317 arr_3[0] = (arr_4[0] << 2) +
318 ((arr_4[1] & 0x30) >> 4);
319 arr_3[1] = ((arr_4[1] & 0xf) << 4) +
320 ((arr_4[2] & 0x3c) >> 2);
321 arr_3[2] = ((arr_4[2] & 0x3) << 6) +
322 arr_4[3];
323
324 for (i = 0; i < 3; i++)
325 ret[ret_cnt++] = arr_3[i];
326
327 i = 0;
328 }
329 }
330
331 if (i) {
332 for (j = i; j < 4; j++)
333 arr_4[j] = 0;
334
335 for (j = 0; j < 4; j++) {
336 if ((p = strchr(b64_data, arr_4[j])) == NULL)
337 return (NULL);
338
339 arr_4[j] = (int)(p - b64_data);
340 }
341 arr_3[0] = (arr_4[0] << 2) +
342 ((arr_4[1] & 0x30) >> 4);
343 arr_3[1] = ((arr_4[1] & 0xf) << 4) +
344 ((arr_4[2] & 0x3c) >> 2);
345 arr_3[2] = ((arr_4[2] & 0x3) << 6) +
346 arr_4[3];
347 for (j = 0; j < (i - 1); j++)
348 ret[ret_cnt++] = arr_3[j];
349 }
350
351 ret[ret_cnt++] = '\0';
352 return (ret);
353 }
354
355 static char *
356 smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp)
357 {
358 smb_scfhandle_t *handle;
359 char *value;
360
361 if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL)
362 return (NULL);
363
364 handle = smb_smf_scf_init(svc_fmri_prefix);
365 if (handle == NULL) {
366 free(value);
367 return (NULL);
368 }
369
370 (void) smb_smf_create_service_pgroup(handle, svc_propgrp);
371
372 if (smb_smf_get_string_property(handle, name, value,
373 sizeof (char) * MAX_VALUE_BUFLEN) != 0) {
374 smb_smf_scf_fini(handle);
375 free(value);
376 return (NULL);
377 }
378
379 smb_smf_scf_fini(handle);
380 return (value);
381
382 }
383
384 static int
385 smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp,
386 char *name, char *value)
387 {
388 smb_scfhandle_t *handle = NULL;
389 int rc = 0;
390
391
392 handle = smb_smf_scf_init(svc_fmri_prefix);
393 if (handle == NULL) {
394 return (1);
395 }
396
397 (void) smb_smf_create_service_pgroup(handle, svc_propgrp);
398
399 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) {
400 smb_smf_scf_fini(handle);
401 return (1);
402 }
403
404 if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK)
405 rc = 1;
406
407 if (smb_smf_end_transaction(handle) != SMBD_SMF_OK)
408 rc = 1;
409
410 smb_smf_scf_fini(handle);
411 return (rc);
412 }
413
414 /*
415 * smb_config_getstr
416 *
417 * Fetch the specified string configuration item from SMF
418 */
419 int
420 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
421 {
422 smb_scfhandle_t *handle;
423 smb_cfg_param_t *cfg;
424 int rc = SMBD_SMF_OK;
425 char *pg;
426 char protbuf[SMB_ENC_LEN];
427 char *tmp;
428
429 *cbuf = '\0';
430 cfg = smb_config_getent(id);
431 assert(cfg->sc_type == SCF_TYPE_ASTRING);
432
433 if (id == SMB_CI_ADS_SITE)
434 return (smb_config_get_idmap_site_name(cbuf, bufsz));
435 if (id == SMB_CI_DOMAIN_SRV)
436 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
437
438 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
439 if (handle == NULL)
440 return (SMBD_SMF_SYSTEM_ERR);
441
442 if (cfg->sc_flags & SMB_CF_PROTECTED) {
443 if ((rc = smb_smf_create_service_pgroup(handle,
444 SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
445 goto error;
446
447 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
448 protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
449 goto error;
450
451 if (*protbuf != '\0') {
452 tmp = smb_base64_decode(protbuf);
453 (void) strlcpy(cbuf, tmp, bufsz);
454 free(tmp);
455 }
456 } else {
457 pg = (cfg->sc_flags & SMB_CF_EXEC) ? SMBD_EXEC_PG_NAME :
458 SMBD_PG_NAME;
459 rc = smb_smf_create_service_pgroup(handle, pg);
460 if (rc == SMBD_SMF_OK)
461 rc = smb_smf_get_string_property(handle, cfg->sc_name,
462 cbuf, bufsz);
463 }
464
465 error:
466 smb_smf_scf_fini(handle);
467 return (rc);
468 }
469
470 /*
471 * Translate the value of an astring SMF property into a binary
472 * IP address. If the value is neither a valid IPv4 nor IPv6
473 * address, attempt to look it up as a hostname using the
474 * configured address type.
475 */
476 int
477 smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr)
478 {
479 int rc, error;
480 int a_family;
481 char ipstr[MAXHOSTNAMELEN];
482 struct hostent *h;
483 smb_cfg_param_t *cfg;
484
485 if (ipaddr == NULL)
486 return (SMBD_SMF_INVALID_ARG);
487
488 bzero(ipaddr, sizeof (smb_inaddr_t));
489 rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr));
490 if (rc == SMBD_SMF_OK) {
491 if (*ipstr == '\0')
492 return (SMBD_SMF_INVALID_ARG);
493
494 if (inet_pton(AF_INET, ipstr, &ipaddr->a_ipv4) == 1) {
495 ipaddr->a_family = AF_INET;
496 return (SMBD_SMF_OK);
497 }
498
499 if (inet_pton(AF_INET6, ipstr, &ipaddr->a_ipv6) == 1) {
500 ipaddr->a_family = AF_INET6;
501 return (SMBD_SMF_OK);
502 }
503
504 /*
505 * The value is neither an IPv4 nor IPv6 address;
506 * so check if it's a hostname.
507 */
508 a_family = smb_config_getbool(SMB_CI_IPV6_ENABLE) ?
509 AF_INET6 : AF_INET;
510 h = getipnodebyname(ipstr, a_family, AI_DEFAULT,
511 &error);
512 if (h != NULL) {
513 bcopy(*(h->h_addr_list), &ipaddr->a_ip,
514 h->h_length);
515 ipaddr->a_family = a_family;
516 freehostent(h);
517 rc = SMBD_SMF_OK;
518 } else {
519 cfg = smb_config_getent(sc_id);
520 syslog(LOG_ERR, "smbd/%s: %s unable to get %s "
521 "address: %d", cfg->sc_name, ipstr,
522 a_family == AF_INET ? "IPv4" : "IPv6", error);
523 rc = SMBD_SMF_INVALID_ARG;
524 }
525 }
526
527 return (rc);
528 }
529
530 /*
531 * smb_config_getnum
532 *
533 * Returns the value of a numeric config param.
534 */
535 int
536 smb_config_getnum(smb_cfg_id_t id, int64_t *cint)
537 {
538 smb_scfhandle_t *handle;
539 smb_cfg_param_t *cfg;
540 int rc = SMBD_SMF_OK;
541
542 *cint = 0;
543 cfg = smb_config_getent(id);
544 assert(cfg->sc_type == SCF_TYPE_INTEGER);
545
546 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
547 if (handle == NULL)
548 return (SMBD_SMF_SYSTEM_ERR);
549
550 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
551 if (rc == SMBD_SMF_OK)
552 rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint);
553 smb_smf_scf_fini(handle);
554
555 return (rc);
556 }
557
558 /*
559 * smb_config_getbool
560 *
561 * Returns the value of a boolean config param.
562 */
563 boolean_t
564 smb_config_getbool(smb_cfg_id_t id)
565 {
566 smb_scfhandle_t *handle;
567 smb_cfg_param_t *cfg;
568 int rc = SMBD_SMF_OK;
569 uint8_t vbool;
570
571 cfg = smb_config_getent(id);
572 assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
573
574 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
575 if (handle == NULL)
576 return (B_FALSE);
577
578 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
579 if (rc == SMBD_SMF_OK)
580 rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool);
581 smb_smf_scf_fini(handle);
582
583 return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE);
584 }
585
586 /*
587 * smb_config_get
588 *
589 * This function returns the value of the requested config
590 * iterm regardless of its type in string format. This should
591 * be used when the config item type is not known by the caller.
592 */
593 int
594 smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz)
595 {
596 smb_cfg_param_t *cfg;
597 int64_t cint;
598 int rc;
599
600 cfg = smb_config_getent(id);
601 switch (cfg->sc_type) {
602 case SCF_TYPE_ASTRING:
603 return (smb_config_getstr(id, cbuf, bufsz));
604
605 case SCF_TYPE_INTEGER:
606 rc = smb_config_getnum(id, &cint);
607 if (rc == SMBD_SMF_OK)
608 (void) snprintf(cbuf, bufsz, "%lld", cint);
609 return (rc);
610
611 case SCF_TYPE_BOOLEAN:
612 if (smb_config_getbool(id))
613 (void) strlcpy(cbuf, "true", bufsz);
614 else
615 (void) strlcpy(cbuf, "false", bufsz);
616 return (SMBD_SMF_OK);
617 }
618
619 return (SMBD_SMF_INVALID_ARG);
620 }
621
622 /*
623 * smb_config_setstr
624 *
625 * Set the specified config param with the given
626 * value.
627 */
628 int
629 smb_config_setstr(smb_cfg_id_t id, char *value)
630 {
631 smb_scfhandle_t *handle;
632 smb_cfg_param_t *cfg;
633 int rc = SMBD_SMF_OK;
634 boolean_t protected;
635 char *tmp = NULL;
636 char *pg;
637
638 cfg = smb_config_getent(id);
639 assert(cfg->sc_type == SCF_TYPE_ASTRING);
640
641 if (id == SMB_CI_ADS_SITE)
642 return (smb_config_set_idmap_site_name(value));
643 if (id == SMB_CI_DOMAIN_SRV)
644 return (smb_config_set_idmap_preferred_dc(value));
645
646 protected = B_FALSE;
647
648 switch (cfg->sc_flags) {
649 case SMB_CF_PROTECTED:
650 protected = B_TRUE;
651 pg = SMBD_PROTECTED_PG_NAME;
652 break;
653 case SMB_CF_EXEC:
654 pg = SMBD_EXEC_PG_NAME;
655 break;
656 default:
657 pg = SMBD_PG_NAME;
658 break;
659 }
660
661 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
662 if (handle == NULL)
663 return (SMBD_SMF_SYSTEM_ERR);
664
665 rc = smb_smf_create_service_pgroup(handle, pg);
666 if (rc == SMBD_SMF_OK)
667 rc = smb_smf_start_transaction(handle);
668
669 if (rc != SMBD_SMF_OK) {
670 smb_smf_scf_fini(handle);
671 return (rc);
672 }
673
674 if (protected && value && (*value != '\0')) {
675 if ((tmp = smb_base64_encode(value)) == NULL) {
676 (void) smb_smf_end_transaction(handle);
677 smb_smf_scf_fini(handle);
678 return (SMBD_SMF_NO_MEMORY);
679 }
680
681 value = tmp;
682 }
683
684 /*
685 * We don't want people who care enough about protecting their data
686 * by requiring encryption to accidentally expose their data
687 * by lowering the protocol, so prevent them from going below 3.0
688 * if encryption is required.
689 * Also, ensure that max_protocol >= min_protocol.
690 */
691 if (id == SMB_CI_MAX_PROTOCOL) {
692 smb_cfg_val_t encrypt;
693 uint32_t min;
694 uint32_t val;
695
696 encrypt = smb_config_get_require(SMB_CI_ENCRYPT);
697 min = smb_config_get_min_protocol();
698 val = smb_convert_version_str(value);
699
700 if (encrypt == SMB_CONFIG_REQUIRED &&
701 val < SMB_VERS_3_0) {
702 syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0"
703 " while smbd/encrypt == required.");
704 rc = SMBD_SMF_INVALID_ARG;
705 } else if (val < min) {
706 syslog(LOG_ERR, "Cannot set smbd/max_protocol to less"
707 " than smbd/min_protocol.");
708 rc = SMBD_SMF_INVALID_ARG;
709 }
710 } else if (id == SMB_CI_MIN_PROTOCOL) {
711 uint32_t max;
712 uint32_t val;
713
714 max = smb_config_get_max_protocol();
715 val = smb_convert_version_str(value);
716
717 if (val > max) {
718 syslog(LOG_ERR, "Cannot set smbd/min_protocol to more"
719 " than smbd/max_protocol.");
720 rc = SMBD_SMF_INVALID_ARG;
721 }
722 }
723
724 if (rc == SMBD_SMF_OK) {
725 rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
726 }
727
728 free(tmp);
729 (void) smb_smf_end_transaction(handle);
730 smb_smf_scf_fini(handle);
731 return (rc);
732 }
733
734 /*
735 * smb_config_setnum
736 *
737 * Sets a numeric configuration iterm
738 */
739 int
740 smb_config_setnum(smb_cfg_id_t id, int64_t value)
741 {
742 smb_scfhandle_t *handle;
743 smb_cfg_param_t *cfg;
744 int rc = SMBD_SMF_OK;
745
746 cfg = smb_config_getent(id);
747 assert(cfg->sc_type == SCF_TYPE_INTEGER);
748
749 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
750 if (handle == NULL)
751 return (SMBD_SMF_SYSTEM_ERR);
752
753 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
754 if (rc == SMBD_SMF_OK)
755 rc = smb_smf_start_transaction(handle);
756
757 if (rc != SMBD_SMF_OK) {
758 smb_smf_scf_fini(handle);
759 return (rc);
760 }
761
762 rc = smb_smf_set_integer_property(handle, cfg->sc_name, value);
763
764 (void) smb_smf_end_transaction(handle);
765 smb_smf_scf_fini(handle);
766 return (rc);
767 }
768
769 /*
770 * smb_config_setbool
771 *
772 * Sets a boolean configuration iterm
773 */
774 int
775 smb_config_setbool(smb_cfg_id_t id, boolean_t value)
776 {
777 smb_scfhandle_t *handle;
778 smb_cfg_param_t *cfg;
779 int rc = SMBD_SMF_OK;
780
781 cfg = smb_config_getent(id);
782 assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
783
784 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
785 if (handle == NULL)
786 return (SMBD_SMF_SYSTEM_ERR);
787
788 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
789 if (rc == SMBD_SMF_OK)
790 rc = smb_smf_start_transaction(handle);
791
792 if (rc != SMBD_SMF_OK) {
793 smb_smf_scf_fini(handle);
794 return (rc);
795 }
796
797 rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value);
798
799 (void) smb_smf_end_transaction(handle);
800 smb_smf_scf_fini(handle);
801 return (rc);
802 }
803
804 /*
805 * smb_config_set
806 *
807 * This function sets the value of the specified config
808 * iterm regardless of its type in string format. This should
809 * be used when the config item type is not known by the caller.
810 */
811 int
812 smb_config_set(smb_cfg_id_t id, char *value)
813 {
814 smb_cfg_param_t *cfg;
815 int64_t cint;
816
817 cfg = smb_config_getent(id);
818 switch (cfg->sc_type) {
819 case SCF_TYPE_ASTRING:
820 return (smb_config_setstr(id, value));
821
822 case SCF_TYPE_INTEGER:
823 cint = atoi(value);
824 return (smb_config_setnum(id, cint));
825
826 case SCF_TYPE_BOOLEAN:
827 return (smb_config_setbool(id, strcasecmp(value, "true") == 0));
828 }
829
830 return (SMBD_SMF_INVALID_ARG);
831 }
832
833 int
834 smb_config_get_debug()
835 {
836 int64_t val64;
837 int val = 0; /* default */
838 smb_scfhandle_t *handle = NULL;
839
840 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
841 if (handle == NULL) {
842 return (val);
843 }
844
845 if (smb_smf_create_service_pgroup(handle,
846 SMBD_PG_NAME) != SMBD_SMF_OK) {
847 smb_smf_scf_fini(handle);
848 return (val);
849 }
850
851 if (smb_smf_get_integer_property(handle, "debug", &val64) != 0) {
852 smb_smf_scf_fini(handle);
853 return (val);
854 }
855 val = (int)val64;
856
857 smb_smf_scf_fini(handle);
858
859 return (val);
860 }
861
862 uint8_t
863 smb_config_get_fg_flag()
864 {
865 uint8_t run_fg = 0; /* Default is to run in daemon mode */
866 smb_scfhandle_t *handle = NULL;
867
868 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
869 if (handle == NULL) {
870 return (run_fg);
871 }
872
873 if (smb_smf_create_service_pgroup(handle,
874 SMBD_PG_NAME) != SMBD_SMF_OK) {
875 smb_smf_scf_fini(handle);
876 return (run_fg);
877 }
878
879 if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) {
880 smb_smf_scf_fini(handle);
881 return (run_fg);
882 }
883
884 smb_smf_scf_fini(handle);
885
886 return (run_fg);
887 }
888
889 /*
890 * smb_config_get_ads_enable
891 *
892 * Returns value of the "config/use_ads" parameter
893 * from the IDMAP SMF configuration repository.
894 *
895 */
896 boolean_t
897 smb_config_get_ads_enable(void)
898 {
899 smb_scfhandle_t *handle = NULL;
900 uint8_t vbool;
901 int rc = 0;
902
903 handle = smb_smf_scf_init(IDMAP_FMRI_PREFIX);
904 if (handle == NULL)
905 return (B_FALSE);
906
907 rc = smb_smf_create_service_pgroup(handle, IDMAP_PG_NAME);
908 if (rc == SMBD_SMF_OK)
909 rc = smb_smf_get_boolean_property(handle, "use_ads", &vbool);
910 smb_smf_scf_fini(handle);
911
912 return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_TRUE);
913 }
914
915 /*
916 * smb_config_get_localsid
917 *
918 * Returns value of the "config/machine_sid" parameter
919 * from the IDMAP SMF configuration repository.
920 * Result is allocated; caller should free.
921 */
922 char *
923 smb_config_get_localsid(void)
924 {
925 return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX,
926 IDMAP_PG_NAME));
927 }
928
929 /*
930 * smb_config_get_localuuid
931 *
932 * Returns value of the "config/machine_uuid" parameter
933 * from the IDMAP SMF configuration repository.
934 *
935 */
936 int
937 smb_config_get_localuuid(uuid_t uu)
938 {
939 char *s;
940
941 uuid_clear(uu);
942 s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX,
943 IDMAP_PG_NAME);
944 if (s == NULL)
945 return (-1);
946
947 if (uuid_parse(s, uu) < 0) {
948 free(s);
949 return (-1);
950 }
951
952 return (0);
953 }
954
955 static int
956 smb_config_get_idmap_preferred_dc(char *cbuf, int bufsz)
957 {
958 char *s;
959 int len, rc = -1;
960
961 s = smb_config_getenv_generic(IDMAP_PREF_DC,
962 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
963 if (s != NULL) {
964 len = strlcpy(cbuf, s, bufsz);
965 if (len < bufsz)
966 rc = 0;
967 free(s);
968 }
969 return (rc);
970 }
971
972 static int
973 smb_config_set_idmap_preferred_dc(char *value)
974 {
975 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
976 IDMAP_PREF_DC, value));
977 }
978
979 static int
980 smb_config_get_idmap_site_name(char *cbuf, int bufsz)
981 {
982 char *s;
983 int len, rc = -1;
984
985 s = smb_config_getenv_generic(IDMAP_SITE_NAME,
986 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
987 if (s != NULL) {
988 len = strlcpy(cbuf, s, bufsz);
989 if (len < bufsz)
990 rc = 0;
991 free(s);
992 }
993 return (rc);
994 }
995
996 static int
997 smb_config_set_idmap_site_name(char *value)
998 {
999 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
1000 IDMAP_SITE_NAME, value));
1001 }
1002
1003 /*
1004 * smb_config_set_idmap_domain
1005 *
1006 * Set the "config/domain_name" parameter from IDMAP SMF repository.
1007 */
1008 int
1009 smb_config_set_idmap_domain(char *value)
1010 {
1011 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
1012 IDMAP_DOMAIN, value));
1013 }
1014
1015 /*
1016 * smb_config_refresh_idmap
1017 *
1018 * Refresh IDMAP SMF service after making changes to its configuration.
1019 */
1020 int
1021 smb_config_refresh_idmap(void)
1022 {
1023 char instance[32];
1024
1025 (void) snprintf(instance, sizeof (instance), "%s:default",
1026 IDMAP_FMRI_PREFIX);
1027 return (smf_refresh_instance(instance));
1028 }
1029
1030 int
1031 smb_config_secmode_fromstr(char *secmode)
1032 {
1033 if (secmode == NULL)
1034 return (SMB_SECMODE_WORKGRP);
1035
1036 if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0)
1037 return (SMB_SECMODE_DOMAIN);
1038
1039 return (SMB_SECMODE_WORKGRP);
1040 }
1041
1042 char *
1043 smb_config_secmode_tostr(int secmode)
1044 {
1045 if (secmode == SMB_SECMODE_DOMAIN)
1046 return (SMB_SECMODE_DOMAIN_STR);
1047
1048 return (SMB_SECMODE_WORKGRP_STR);
1049 }
1050
1051 int
1052 smb_config_get_secmode()
1053 {
1054 char p[16];
1055
1056 (void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p));
1057 return (smb_config_secmode_fromstr(p));
1058 }
1059
1060 int
1061 smb_config_set_secmode(int secmode)
1062 {
1063 char *p;
1064
1065 p = smb_config_secmode_tostr(secmode);
1066 return (smb_config_setstr(SMB_CI_SECURITY, p));
1067 }
1068
1069 void
1070 smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
1071 char *guid)
1072 {
1073 if (domain)
1074 (void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain,
1075 NETBIOS_NAME_SZ);
1076
1077 if (fqdn)
1078 (void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn,
1079 MAXHOSTNAMELEN);
1080
1081 if (sid)
1082 (void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid,
1083 SMB_SID_STRSZ);
1084
1085 if (forest)
1086 (void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest,
1087 MAXHOSTNAMELEN);
1088
1089 if (guid)
1090 (void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid,
1091 UUID_PRINTABLE_STRING_LENGTH);
1092 }
1093
1094 void
1095 smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
1096 char *guid)
1097 {
1098 if (domain)
1099 (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain);
1100 if (fqdn)
1101 (void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn);
1102 if (sid)
1103 (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid);
1104 if (forest)
1105 (void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest);
1106 if (guid)
1107 (void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid);
1108 }
1109
1110 /*
1111 * The version stored in SMF in string format as N.N where
1112 * N is a number defined by Microsoft. The first number represents
1113 * the major version and the second number is the minor version.
1114 * Current defined values can be found here in 'ver_table'.
1115 *
1116 * This function reads the SMF string value and converts it to
1117 * two numbers returned in the given 'version' structure.
1118 * Current default version number is 5.0 which is for Windows 2000.
1119 */
1120 void
1121 smb_config_get_version(smb_version_t *version)
1122 {
1123 smb_version_t tmpver;
1124 char verstr[SMB_VERSTR_LEN];
1125 char *p;
1126 int rc, i;
1127 static smb_version_t ver_table [] = {
1128 { 0, SMB_MAJOR_NT, SMB_MINOR_NT, 1381, 0 },
1129 { 0, SMB_MAJOR_2000, SMB_MINOR_2000, 2195, 0 },
1130 { 0, SMB_MAJOR_XP, SMB_MINOR_XP, 2196, 0 },
1131 { 0, SMB_MAJOR_2003, SMB_MINOR_2003, 2196, 0 },
1132 { 0, SMB_MAJOR_VISTA, SMB_MINOR_VISTA, 6000, 0 },
1133 { 0, SMB_MAJOR_2008, SMB_MINOR_2008, 6000, 0 },
1134 { 0, SMB_MAJOR_2008R2, SMB_MINOR_2008R2, 7007, 0 },
1135 { 0, SMB_MAJOR_7, SMB_MINOR_7, 7007, 0 }
1136 };
1137
1138 *version = ver_table[1];
1139 version->sv_size = sizeof (smb_version_t);
1140
1141 rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr));
1142 if (rc != SMBD_SMF_OK)
1143 return;
1144
1145 if ((p = strchr(verstr, '.')) == NULL)
1146 return;
1147
1148 *p = '\0';
1149 tmpver.sv_major = (uint8_t)atoi(verstr);
1150 tmpver.sv_minor = (uint8_t)atoi(p + 1);
1151
1152 for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) {
1153 if ((tmpver.sv_major == ver_table[i].sv_major) &&
1154 (tmpver.sv_minor == ver_table[i].sv_minor)) {
1155 *version = ver_table[i];
1156 version->sv_size = sizeof (smb_version_t);
1157 break;
1158 }
1159 }
1160 }
1161
1162 /*
1163 * Reads share exec script properties
1164 */
1165 uint32_t
1166 smb_config_get_execinfo(char *map, char *unmap, size_t bufsz)
1167 {
1168 char buf[MAXPATHLEN];
1169 uint32_t flags = 0;
1170
1171 if (map == NULL) {
1172 map = buf;
1173 bufsz = MAXPATHLEN;
1174 }
1175
1176 *map = '\0';
1177 (void) smb_config_getstr(SMB_CI_MAP, map, bufsz);
1178 if (*map != '\0')
1179 flags |= SMB_EXEC_MAP;
1180
1181 if (unmap == NULL) {
1182 unmap = buf;
1183 bufsz = MAXPATHLEN;
1184 }
1185
1186 *unmap = '\0';
1187 (void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz);
1188 if (*unmap != '\0')
1189 flags |= SMB_EXEC_UNMAP;
1190
1191 *buf = '\0';
1192 (void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
1193 if (*buf != '\0')
1194 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1195 flags |= SMB_EXEC_TERM;
1196
1197 return (flags);
1198 }
1199
1200 static smb_cfg_param_t *
1201 smb_config_getent(smb_cfg_id_t id)
1202 {
1203 int i;
1204
1205 for (i = 0; i < SMB_CI_MAX; i++)
1206 if (smb_cfg_table[i].sc_id == id)
1207 return (&smb_cfg_table[id]);
1208
1209 assert(0);
1210 return (NULL);
1211 }
1212
1213 static uint32_t
1214 smb_config_get_protocol(smb_cfg_id_t id, char *name, uint32_t default_val)
1215 {
1216 char str[SMB_VERSTR_LEN];
1217 int rc;
1218 uint32_t val;
1219
1220 rc = smb_config_getstr(id, str, sizeof (str));
1221 if (rc == SMBD_SMF_OK) {
1222 val = smb_convert_version_str(str);
1223 if (val != 0)
1224 return (val);
1225 if (str[0] != '\0') {
1226 syslog(LOG_ERR, "smbd/%s value invalid: %s", name, str);
1227 }
1228 }
1229
1230 return (default_val);
1231 }
1232
1233 /*
1234 * The service manifest has empty values by default for min_protocol and
1235 * max_protocol. The expectation is that when those values are empty, we don't
1236 * constrain the range of supported protocol versions (and allow use of the
1237 * whole range that we implement). For that reason, this should usually be the
1238 * highest protocol version we implement.
1239 */
1240 uint32_t max_protocol_default = SMB_VERS_3_11;
1241
1242 uint32_t
1243 smb_config_get_max_protocol(void)
1244 {
1245 uint32_t max;
1246
1247 max = smb_config_get_protocol(SMB_CI_MAX_PROTOCOL, "max_protocol",
1248 max_protocol_default);
1249
1250 return (max);
1251 }
1252
1253 /*
1254 * This should eventually be SMB_VERS_2_BASE
1255 */
1256 uint32_t min_protocol_default = SMB_VERS_1;
1257
1258 uint32_t
1259 smb_config_get_min_protocol(void)
1260 {
1261 uint32_t min;
1262
1263 min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol",
1264 min_protocol_default);
1265
1266 return (min);
1267 }
1268
1269 int
1270 smb_config_check_protocol(char *value)
1271 {
1272 if (smb_convert_version_str(value) != 0)
1273 return (0);
1274
1275 return (-1);
1276 }
1277
1278 /*
1279 * Only SMB 3.x supports encryption.
1280 * SMB 3.0.2 uses AES128-CCM only.
1281 * SMB 3.1.1 - AES128-CCM or AES128-GCM.
1282 */
1283 uint16_t
1284 smb31_config_get_encrypt_cipher(void)
1285 {
1286 uint32_t max_proto = smb_config_get_max_protocol();
1287 uint16_t cipher = SMB3_CIPHER_AES128_GCM; /* by default AES128-GCM */
1288 char str[12];
1289 int i;
1290
1291 if (max_proto < SMB_VERS_3_11)
1292 return (SMB3_CIPHER_NONE);
1293
1294 /* SMB 3.1.1 */
1295 if (smb_config_getstr(SMB_CI_ENCRYPT_CIPHER, str, sizeof (str))
1296 == SMBD_SMF_OK) {
1297 for (i = 0; smb31_encrypt_ciphers[i].str != NULL; i++) {
1298 if (strcmp(str, smb31_encrypt_ciphers[i].str) == 0)
1299 cipher = smb31_encrypt_ciphers[i].val;
1300 }
1301 }
1302
1303 return (cipher);
1304 }
1305
1306 /*
1307 * If smb2_enable is present and max_protocol is empty,
1308 * set max_protocol. Delete smb2_enable.
1309 */
1310 static void
1311 upgrade_smb2_enable()
1312 {
1313 smb_scfhandle_t *handle;
1314 char *s2e_name = "smb2_enable";
1315 char *s2e_sval;
1316 uint8_t s2e_bval;
1317 char *maxp_name = "max_protocol";
1318 char *maxp_sval;
1319 char verstr[SMB_VERSTR_LEN];
1320 int rc;
1321
1322 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
1323 if (handle == NULL)
1324 return;
1325 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
1326 if (rc != SMBD_SMF_OK)
1327 goto out;
1328
1329 /* Is there an "smb2_enable" property? */
1330 rc = smb_smf_get_boolean_property(handle, s2e_name, &s2e_bval);
1331 if (rc != SMBD_SMF_OK) {
1332 syslog(LOG_DEBUG, "upgrade: smb2_enable not found");
1333 goto out;
1334 }
1335
1336 /*
1337 * We will try to delete the smb2_enable property, so we need
1338 * the transaction to start now, before we modify max_protocol
1339 */
1340 if ((rc = smb_smf_start_transaction(handle)) != 0) {
1341 syslog(LOG_DEBUG, "upgrade_smb2_enable: start trans (%d)", rc);
1342 goto out;
1343 }
1344
1345 /*
1346 * Old (smb2_enable) property exists.
1347 * Does the new one? (max_protocol)
1348 */
1349 rc = smb_smf_get_string_property(handle, maxp_name,
1350 verstr, sizeof (verstr));
1351 if (rc == SMBD_SMF_OK && !smb_config_check_protocol(verstr)) {
1352 syslog(LOG_DEBUG, "upgrade: found %s = %s",
1353 maxp_name, verstr);
1354 /* Leave existing max_protocol as we found it. */
1355 } else {
1356 /*
1357 * New property missing or invalid.
1358 * Upgrade from "smb2_enable".
1359 */
1360 if (s2e_bval == 0) {
1361 s2e_sval = "false";
1362 maxp_sval = "1";
1363 } else {
1364 s2e_sval = "true";
1365 maxp_sval = "2.1";
1366 }
1367 /*
1368 * Note: Need this in the same transaction as the
1369 * delete of smb2_enable below.
1370 */
1371 rc = smb_smf_set_string_property(handle, maxp_name, maxp_sval);
1372 if (rc != SMBD_SMF_OK) {
1373 syslog(LOG_ERR, "failed to set smbd/%d (%d)",
1374 maxp_name, rc);
1375 goto out;
1376 }
1377 syslog(LOG_INFO, "upgrade smbd/smb2_enable=%s "
1378 "converted to smbd/max_protocol=%s",
1379 s2e_sval, maxp_sval);
1380 }
1381
1382 /*
1383 * Delete the old smb2_enable property.
1384 */
1385 if ((rc = smb_smf_delete_property(handle, s2e_name)) != 0) {
1386 syslog(LOG_DEBUG, "upgrade_smb2_enable: delete prop (%d)", rc);
1387 } else if ((rc = smb_smf_end_transaction(handle)) != 0) {
1388 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1389 }
1390 if (rc != 0) {
1391 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1392 s2e_name, rc);
1393 }
1394
1395 out:
1396 (void) smb_smf_end_transaction(handle);
1397 smb_smf_scf_fini(handle);
1398 }
1399
1400
1401 /*
1402 * Run once at startup convert old SMF settings to current.
1403 */
1404 void
1405 smb_config_upgrade(void)
1406 {
1407 upgrade_smb2_enable();
1408 }
1409
1410 smb_cfg_val_t
1411 smb_config_get_require(smb_cfg_id_t id)
1412 {
1413 int rc;
1414 char str[sizeof ("required")];
1415
1416 rc = smb_config_getstr(id, str, sizeof (str));
1417 if (rc != SMBD_SMF_OK)
1418 return (SMB_CONFIG_DISABLED);
1419
1420 if (strncmp(str, "required", sizeof (str)) == 0)
1421 return (SMB_CONFIG_REQUIRED);
1422 if (strncmp(str, "enabled", sizeof (str)) == 0)
1423 return (SMB_CONFIG_ENABLED);
1424
1425 return (SMB_CONFIG_DISABLED);
1426 }