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 2015 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>
49 uint32_t sc_flags;
50 } smb_cfg_param_t;
51
52 struct str_val {
53 char *str;
54 uint32_t val;
55 };
56
57 /*
58 * config parameter flags
59 */
60 #define SMB_CF_PROTECTED 0x01
61 #define SMB_CF_EXEC 0x02
62
63 /* idmap SMF fmri and Property Group */
64 #define IDMAP_FMRI_PREFIX "system/idmap"
65 #define MACHINE_SID "machine_sid"
66 #define MACHINE_UUID "machine_uuid"
67 #define IDMAP_DOMAIN "domain_name"
68 #define IDMAP_PREF_DC "preferred_dc"
69 #define IDMAP_PG_NAME "config"
70
71 #define SMB_SECMODE_WORKGRP_STR "workgroup"
72 #define SMB_SECMODE_DOMAIN_STR "domain"
73
74 #define SMB_ENC_LEN 1024
75 #define SMB_DEC_LEN 256
76
77 static char *b64_data =
78 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
79
80 static smb_cfg_param_t smb_cfg_table[] =
81 {
82 {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
83
84 /* Oplock configuration, Kernel Only */
85 {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
86
87 /* Autohome configuration */
88 {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
128
129 {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
130 SMB_CF_PROTECTED},
131
132 {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
133 {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
134 {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
135 {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
136 {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
137 {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
138 {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
139 {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
140 {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
141 {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
142 {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
143 {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
144 {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
145 {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
146 {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
147 {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},
148
149 /* SMB_CI_MAX */
150 };
151
152 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
153
154 static boolean_t smb_is_base64(unsigned char c);
155 static char *smb_base64_encode(char *str_to_encode);
156 static char *smb_base64_decode(char *encoded_str);
157 static int smb_config_get_idmap_preferred_dc(char *, int);
158 static int smb_config_set_idmap_preferred_dc(char *);
159
160 char *
161 smb_config_getname(smb_cfg_id_t id)
162 {
163 smb_cfg_param_t *cfg;
164 cfg = smb_config_getent(id);
165 return (cfg->sc_name);
166 }
167
168 static boolean_t
169 smb_is_base64(unsigned char c)
170 {
171 return (isalnum(c) || (c == '+') || (c == '/'));
172 }
173
174 /*
175 * smb_base64_encode
176 *
177 * Encode a string using base64 algorithm.
178 * Caller should free the returned buffer when done.
179 */
360
361 /*
362 * smb_config_getstr
363 *
364 * Fetch the specified string configuration item from SMF
365 */
366 int
367 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
368 {
369 smb_scfhandle_t *handle;
370 smb_cfg_param_t *cfg;
371 int rc = SMBD_SMF_OK;
372 char *pg;
373 char protbuf[SMB_ENC_LEN];
374 char *tmp;
375
376 *cbuf = '\0';
377 cfg = smb_config_getent(id);
378 assert(cfg->sc_type == SCF_TYPE_ASTRING);
379
380 if (id == SMB_CI_DOMAIN_SRV)
381 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
382
383 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
384 if (handle == NULL)
385 return (SMBD_SMF_SYSTEM_ERR);
386
387 if (cfg->sc_flags & SMB_CF_PROTECTED) {
388 if ((rc = smb_smf_create_service_pgroup(handle,
389 SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
390 goto error;
391
392 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
393 protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
394 goto error;
395
396 if (*protbuf != '\0') {
397 tmp = smb_base64_decode(protbuf);
398 (void) strlcpy(cbuf, tmp, bufsz);
399 free(tmp);
566
567 /*
568 * smb_config_setstr
569 *
570 * Set the specified config param with the given
571 * value.
572 */
573 int
574 smb_config_setstr(smb_cfg_id_t id, char *value)
575 {
576 smb_scfhandle_t *handle;
577 smb_cfg_param_t *cfg;
578 int rc = SMBD_SMF_OK;
579 boolean_t protected;
580 char *tmp = NULL;
581 char *pg;
582
583 cfg = smb_config_getent(id);
584 assert(cfg->sc_type == SCF_TYPE_ASTRING);
585
586 if (id == SMB_CI_DOMAIN_SRV)
587 return (smb_config_set_idmap_preferred_dc(value));
588
589 protected = B_FALSE;
590
591 switch (cfg->sc_flags) {
592 case SMB_CF_PROTECTED:
593 protected = B_TRUE;
594 pg = SMBD_PROTECTED_PG_NAME;
595 break;
596 case SMB_CF_EXEC:
597 pg = SMBD_EXEC_PG_NAME;
598 break;
599 default:
600 pg = SMBD_PG_NAME;
601 break;
602 }
603
604 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
605 if (handle == NULL)
607
608 rc = smb_smf_create_service_pgroup(handle, pg);
609 if (rc == SMBD_SMF_OK)
610 rc = smb_smf_start_transaction(handle);
611
612 if (rc != SMBD_SMF_OK) {
613 smb_smf_scf_fini(handle);
614 return (rc);
615 }
616
617 if (protected && value && (*value != '\0')) {
618 if ((tmp = smb_base64_encode(value)) == NULL) {
619 (void) smb_smf_end_transaction(handle);
620 smb_smf_scf_fini(handle);
621 return (SMBD_SMF_NO_MEMORY);
622 }
623
624 value = tmp;
625 }
626
627 rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
628
629 free(tmp);
630 (void) smb_smf_end_transaction(handle);
631 smb_smf_scf_fini(handle);
632 return (rc);
633 }
634
635 /*
636 * smb_config_setnum
637 *
638 * Sets a numeric configuration iterm
639 */
640 int
641 smb_config_setnum(smb_cfg_id_t id, int64_t value)
642 {
643 smb_scfhandle_t *handle;
644 smb_cfg_param_t *cfg;
645 int rc = SMBD_SMF_OK;
646
647 cfg = smb_config_getent(id);
860 int len, rc = -1;
861
862 s = smb_config_getenv_generic(IDMAP_PREF_DC,
863 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
864 if (s != NULL) {
865 len = strlcpy(cbuf, s, bufsz);
866 if (len < bufsz)
867 rc = 0;
868 free(s);
869 }
870 return (rc);
871 }
872
873 static int
874 smb_config_set_idmap_preferred_dc(char *value)
875 {
876 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
877 IDMAP_PREF_DC, value));
878 }
879
880 /*
881 * smb_config_set_idmap_domain
882 *
883 * Set the "config/domain_name" parameter from IDMAP SMF repository.
884 */
885 int
886 smb_config_set_idmap_domain(char *value)
887 {
888 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
889 IDMAP_DOMAIN, value));
890 }
891
892 /*
893 * smb_config_refresh_idmap
894 *
895 * Refresh IDMAP SMF service after making changes to its configuration.
896 */
897 int
898 smb_config_refresh_idmap(void)
899 {
1070 if (*buf != '\0')
1071 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1072 flags |= SMB_EXEC_TERM;
1073
1074 return (flags);
1075 }
1076
1077 static smb_cfg_param_t *
1078 smb_config_getent(smb_cfg_id_t id)
1079 {
1080 int i;
1081
1082 for (i = 0; i < SMB_CI_MAX; i++)
1083 if (smb_cfg_table[i].sc_id == id)
1084 return (&smb_cfg_table[id]);
1085
1086 assert(0);
1087 return (NULL);
1088 }
1089
1090
1091 /*
1092 * We store the max SMB protocol version in SMF as a string,
1093 * (for convenience of svccfg etc) but the programmatic get/set
1094 * interfaces use the numeric form.
1095 *
1096 * The numeric values are as defined in the [MS-SMB2] spec.
1097 * except for how we represent "1" (for SMB1) which is an
1098 * arbitrary value below SMB2_VERS_BASE.
1099 */
1100 static struct str_val
1101 smb_versions[] = {
1102 { "3.0", SMB_VERS_3_0 },
1103 { "2.1", SMB_VERS_2_1 },
1104 { "2.002", SMB_VERS_2_002 },
1105 { "1", SMB_VERS_1 },
1106 { NULL, 0 }
1107 };
1108
1109 /*
1110 * This really should be the latest (SMB_VERS_3_0)
1111 * but we're being cautious with SMB3 for a while.
1112 */
1113 uint32_t max_protocol_default = SMB_VERS_2_1;
1114
1115 uint32_t
1116 smb_config_get_max_protocol(void)
1117 {
1118 char str[SMB_VERSTR_LEN];
1119 int i, rc;
1120
1121 rc = smb_config_getstr(SMB_CI_MAX_PROTOCOL, str, sizeof (str));
1122 if (rc == SMBD_SMF_OK) {
1123 for (i = 0; smb_versions[i].str != NULL; i++) {
1124 if (strcmp(str, smb_versions[i].str) == 0)
1125 return (smb_versions[i].val);
1126 }
1127 if (str[0] != '\0') {
1128 syslog(LOG_ERR, "smbd/max_protocol value invalid");
1129 }
1130 }
1131
1132 return (max_protocol_default);
1133 }
1134
1135 int
1136 smb_config_check_protocol(char *value)
1137 {
1138 int i;
1139
1140 for (i = 0; smb_versions[i].str != NULL; i++) {
1141 if (strcmp(value, smb_versions[i].str) == 0)
1142 return (0);
1143 }
1144
1145 return (-1);
1146 }
1147
1148 /*
1149 * If smb2_enable is present and max_protocol is empty,
1150 * set max_protocol. Delete smb2_enable.
1151 */
1152 static void
1153 upgrade_smb2_enable()
1154 {
1155 smb_scfhandle_t *handle;
1156 char *s2e_name = "smb2_enable";
1157 char *s2e_sval;
1158 uint8_t s2e_bval;
1159 char *maxp_name = "max_protocol";
1160 char *maxp_sval;
1161 char verstr[SMB_VERSTR_LEN];
1162 int rc;
1163
1230 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1231 }
1232 if (rc != 0) {
1233 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1234 s2e_name, rc);
1235 }
1236
1237 out:
1238 (void) smb_smf_end_transaction(handle);
1239 smb_smf_scf_fini(handle);
1240 }
1241
1242
1243 /*
1244 * Run once at startup convert old SMF settings to current.
1245 */
1246 void
1247 smb_config_upgrade(void)
1248 {
1249 upgrade_smb2_enable();
1250 }
|
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 */
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>
49 uint32_t sc_flags;
50 } smb_cfg_param_t;
51
52 struct str_val {
53 char *str;
54 uint32_t val;
55 };
56
57 /*
58 * config parameter flags
59 */
60 #define SMB_CF_PROTECTED 0x01
61 #define SMB_CF_EXEC 0x02
62
63 /* idmap SMF fmri and Property Group */
64 #define IDMAP_FMRI_PREFIX "system/idmap"
65 #define MACHINE_SID "machine_sid"
66 #define MACHINE_UUID "machine_uuid"
67 #define IDMAP_DOMAIN "domain_name"
68 #define IDMAP_PREF_DC "preferred_dc"
69 #define IDMAP_SITE_NAME "site_name"
70 #define IDMAP_PG_NAME "config"
71
72 #define SMB_SECMODE_WORKGRP_STR "workgroup"
73 #define SMB_SECMODE_DOMAIN_STR "domain"
74
75 #define SMB_ENC_LEN 1024
76 #define SMB_DEC_LEN 256
77
78 static char *b64_data =
79 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80
81 static smb_cfg_param_t smb_cfg_table[] =
82 {
83 {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
84
85 /* Oplock configuration, Kernel Only */
86 {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
87
88 /* Autohome configuration */
89 {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
129
130 {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
131 SMB_CF_PROTECTED},
132
133 {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
134 {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
135 {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
136 {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
137 {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
138 {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
139 {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
140 {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
141 {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
142 {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
143 {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
144 {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
145 {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
146 {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
147 {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
148 {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},
149 {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0},
150 {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0},
151 {SMB_CI_BYPASS_TRAVERSE_CHECKING,
152 "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0},
153
154 /* SMB_CI_MAX */
155 };
156
157 /*
158 * We store the max SMB protocol version in SMF as a string,
159 * (for convenience of svccfg etc) but the programmatic get/set
160 * interfaces use the numeric form.
161 *
162 * The numeric values are as defined in the [MS-SMB2] spec.
163 * except for how we represent "1" (for SMB1) which is an
164 * arbitrary value below SMB2_VERS_BASE.
165 */
166 static struct str_val
167 smb_versions[] = {
168 { "3.02", SMB_VERS_3_02 },
169 { "3.0", SMB_VERS_3_0 },
170 { "2.1", SMB_VERS_2_1 },
171 { "2.002", SMB_VERS_2_002 },
172 { "1", SMB_VERS_1 },
173 { NULL, 0 }
174 };
175
176 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
177
178 static boolean_t smb_is_base64(unsigned char c);
179 static char *smb_base64_encode(char *str_to_encode);
180 static char *smb_base64_decode(char *encoded_str);
181 static int smb_config_get_idmap_preferred_dc(char *, int);
182 static int smb_config_set_idmap_preferred_dc(char *);
183 static int smb_config_get_idmap_site_name(char *, int);
184 static int smb_config_set_idmap_site_name(char *);
185
186 static uint32_t
187 smb_convert_version_str(const char *version)
188 {
189 uint32_t dialect = 0;
190 int i;
191
192 for (i = 0; smb_versions[i].str != NULL; i++) {
193 if (strcmp(version, smb_versions[i].str) == 0)
194 dialect = smb_versions[i].val;
195 }
196
197 return (dialect);
198 }
199
200 char *
201 smb_config_getname(smb_cfg_id_t id)
202 {
203 smb_cfg_param_t *cfg;
204 cfg = smb_config_getent(id);
205 return (cfg->sc_name);
206 }
207
208 static boolean_t
209 smb_is_base64(unsigned char c)
210 {
211 return (isalnum(c) || (c == '+') || (c == '/'));
212 }
213
214 /*
215 * smb_base64_encode
216 *
217 * Encode a string using base64 algorithm.
218 * Caller should free the returned buffer when done.
219 */
400
401 /*
402 * smb_config_getstr
403 *
404 * Fetch the specified string configuration item from SMF
405 */
406 int
407 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
408 {
409 smb_scfhandle_t *handle;
410 smb_cfg_param_t *cfg;
411 int rc = SMBD_SMF_OK;
412 char *pg;
413 char protbuf[SMB_ENC_LEN];
414 char *tmp;
415
416 *cbuf = '\0';
417 cfg = smb_config_getent(id);
418 assert(cfg->sc_type == SCF_TYPE_ASTRING);
419
420 if (id == SMB_CI_ADS_SITE)
421 return (smb_config_get_idmap_site_name(cbuf, bufsz));
422 if (id == SMB_CI_DOMAIN_SRV)
423 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
424
425 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
426 if (handle == NULL)
427 return (SMBD_SMF_SYSTEM_ERR);
428
429 if (cfg->sc_flags & SMB_CF_PROTECTED) {
430 if ((rc = smb_smf_create_service_pgroup(handle,
431 SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
432 goto error;
433
434 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
435 protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
436 goto error;
437
438 if (*protbuf != '\0') {
439 tmp = smb_base64_decode(protbuf);
440 (void) strlcpy(cbuf, tmp, bufsz);
441 free(tmp);
608
609 /*
610 * smb_config_setstr
611 *
612 * Set the specified config param with the given
613 * value.
614 */
615 int
616 smb_config_setstr(smb_cfg_id_t id, char *value)
617 {
618 smb_scfhandle_t *handle;
619 smb_cfg_param_t *cfg;
620 int rc = SMBD_SMF_OK;
621 boolean_t protected;
622 char *tmp = NULL;
623 char *pg;
624
625 cfg = smb_config_getent(id);
626 assert(cfg->sc_type == SCF_TYPE_ASTRING);
627
628 if (id == SMB_CI_ADS_SITE)
629 return (smb_config_set_idmap_site_name(value));
630 if (id == SMB_CI_DOMAIN_SRV)
631 return (smb_config_set_idmap_preferred_dc(value));
632
633 protected = B_FALSE;
634
635 switch (cfg->sc_flags) {
636 case SMB_CF_PROTECTED:
637 protected = B_TRUE;
638 pg = SMBD_PROTECTED_PG_NAME;
639 break;
640 case SMB_CF_EXEC:
641 pg = SMBD_EXEC_PG_NAME;
642 break;
643 default:
644 pg = SMBD_PG_NAME;
645 break;
646 }
647
648 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
649 if (handle == NULL)
651
652 rc = smb_smf_create_service_pgroup(handle, pg);
653 if (rc == SMBD_SMF_OK)
654 rc = smb_smf_start_transaction(handle);
655
656 if (rc != SMBD_SMF_OK) {
657 smb_smf_scf_fini(handle);
658 return (rc);
659 }
660
661 if (protected && value && (*value != '\0')) {
662 if ((tmp = smb_base64_encode(value)) == NULL) {
663 (void) smb_smf_end_transaction(handle);
664 smb_smf_scf_fini(handle);
665 return (SMBD_SMF_NO_MEMORY);
666 }
667
668 value = tmp;
669 }
670
671 /*
672 * We don't want people who care enough about protecting their data
673 * by requiring encryption to accidentally expose their data
674 * by lowering the protocol, so prevent them from going below 3.0
675 * if encryption is required.
676 * Also, ensure that max_protocol >= min_protocol.
677 */
678 if (id == SMB_CI_MAX_PROTOCOL) {
679 smb_cfg_val_t encrypt;
680 uint32_t min;
681 uint32_t val;
682
683 encrypt = smb_config_get_require(SMB_CI_ENCRYPT);
684 min = smb_config_get_min_protocol();
685 val = smb_convert_version_str(value);
686
687 if (encrypt == SMB_CONFIG_REQUIRED &&
688 val < SMB_VERS_3_0) {
689 syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0"
690 " while smbd/encrypt == required.");
691 rc = SMBD_SMF_INVALID_ARG;
692 } else if (val < min) {
693 syslog(LOG_ERR, "Cannot set smbd/max_protocol to less"
694 " than smbd/min_protocol.");
695 rc = SMBD_SMF_INVALID_ARG;
696 }
697 } else if (id == SMB_CI_MIN_PROTOCOL) {
698 uint32_t max;
699 uint32_t val;
700
701 max = smb_config_get_max_protocol();
702 val = smb_convert_version_str(value);
703
704 if (val > max) {
705 syslog(LOG_ERR, "Cannot set smbd/min_protocol to more"
706 " than smbd/max_protocol.");
707 rc = SMBD_SMF_INVALID_ARG;
708 }
709 }
710
711 if (rc == SMBD_SMF_OK) {
712 rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
713 }
714
715 free(tmp);
716 (void) smb_smf_end_transaction(handle);
717 smb_smf_scf_fini(handle);
718 return (rc);
719 }
720
721 /*
722 * smb_config_setnum
723 *
724 * Sets a numeric configuration iterm
725 */
726 int
727 smb_config_setnum(smb_cfg_id_t id, int64_t value)
728 {
729 smb_scfhandle_t *handle;
730 smb_cfg_param_t *cfg;
731 int rc = SMBD_SMF_OK;
732
733 cfg = smb_config_getent(id);
946 int len, rc = -1;
947
948 s = smb_config_getenv_generic(IDMAP_PREF_DC,
949 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
950 if (s != NULL) {
951 len = strlcpy(cbuf, s, bufsz);
952 if (len < bufsz)
953 rc = 0;
954 free(s);
955 }
956 return (rc);
957 }
958
959 static int
960 smb_config_set_idmap_preferred_dc(char *value)
961 {
962 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
963 IDMAP_PREF_DC, value));
964 }
965
966 static int
967 smb_config_get_idmap_site_name(char *cbuf, int bufsz)
968 {
969 char *s;
970 int len, rc = -1;
971
972 s = smb_config_getenv_generic(IDMAP_SITE_NAME,
973 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
974 if (s != NULL) {
975 len = strlcpy(cbuf, s, bufsz);
976 if (len < bufsz)
977 rc = 0;
978 free(s);
979 }
980 return (rc);
981 }
982
983 static int
984 smb_config_set_idmap_site_name(char *value)
985 {
986 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
987 IDMAP_SITE_NAME, value));
988 }
989
990 /*
991 * smb_config_set_idmap_domain
992 *
993 * Set the "config/domain_name" parameter from IDMAP SMF repository.
994 */
995 int
996 smb_config_set_idmap_domain(char *value)
997 {
998 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
999 IDMAP_DOMAIN, value));
1000 }
1001
1002 /*
1003 * smb_config_refresh_idmap
1004 *
1005 * Refresh IDMAP SMF service after making changes to its configuration.
1006 */
1007 int
1008 smb_config_refresh_idmap(void)
1009 {
1180 if (*buf != '\0')
1181 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1182 flags |= SMB_EXEC_TERM;
1183
1184 return (flags);
1185 }
1186
1187 static smb_cfg_param_t *
1188 smb_config_getent(smb_cfg_id_t id)
1189 {
1190 int i;
1191
1192 for (i = 0; i < SMB_CI_MAX; i++)
1193 if (smb_cfg_table[i].sc_id == id)
1194 return (&smb_cfg_table[id]);
1195
1196 assert(0);
1197 return (NULL);
1198 }
1199
1200 static uint32_t
1201 smb_config_get_protocol(smb_cfg_id_t id, char *name, uint32_t default_val)
1202 {
1203 char str[SMB_VERSTR_LEN];
1204 int rc;
1205 uint32_t val;
1206
1207 rc = smb_config_getstr(id, str, sizeof (str));
1208 if (rc == SMBD_SMF_OK) {
1209 val = smb_convert_version_str(str);
1210 if (val != 0)
1211 return (val);
1212 if (str[0] != '\0') {
1213 syslog(LOG_ERR, "smbd/%s value invalid: %s", name, str);
1214 }
1215 }
1216
1217 return (default_val);
1218 }
1219
1220 /*
1221 * The service manifest has empty values by default for min_protocol and
1222 * max_protocol. The expectation is that when those values are empty, we don't
1223 * constrain the range of supported protocol versions (and allow use of the
1224 * whole range that we implement). For that reason, this should usually be the
1225 * highest protocol version we implement.
1226 */
1227 uint32_t max_protocol_default = SMB_VERS_3_02;
1228
1229 uint32_t
1230 smb_config_get_max_protocol(void)
1231 {
1232 uint32_t max;
1233
1234 max = smb_config_get_protocol(SMB_CI_MAX_PROTOCOL, "max_protocol",
1235 max_protocol_default);
1236
1237 return (max);
1238 }
1239
1240 /*
1241 * This should eventually be SMB_VERS_2_BASE
1242 */
1243 uint32_t min_protocol_default = SMB_VERS_1;
1244
1245 uint32_t
1246 smb_config_get_min_protocol(void)
1247 {
1248 uint32_t min;
1249
1250 min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol",
1251 min_protocol_default);
1252
1253 return (min);
1254 }
1255
1256 int
1257 smb_config_check_protocol(char *value)
1258 {
1259 if (smb_convert_version_str(value) != 0)
1260 return (0);
1261
1262 return (-1);
1263 }
1264
1265 /*
1266 * If smb2_enable is present and max_protocol is empty,
1267 * set max_protocol. Delete smb2_enable.
1268 */
1269 static void
1270 upgrade_smb2_enable()
1271 {
1272 smb_scfhandle_t *handle;
1273 char *s2e_name = "smb2_enable";
1274 char *s2e_sval;
1275 uint8_t s2e_bval;
1276 char *maxp_name = "max_protocol";
1277 char *maxp_sval;
1278 char verstr[SMB_VERSTR_LEN];
1279 int rc;
1280
1347 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1348 }
1349 if (rc != 0) {
1350 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1351 s2e_name, rc);
1352 }
1353
1354 out:
1355 (void) smb_smf_end_transaction(handle);
1356 smb_smf_scf_fini(handle);
1357 }
1358
1359
1360 /*
1361 * Run once at startup convert old SMF settings to current.
1362 */
1363 void
1364 smb_config_upgrade(void)
1365 {
1366 upgrade_smb2_enable();
1367 }
1368
1369 smb_cfg_val_t
1370 smb_config_get_require(smb_cfg_id_t id)
1371 {
1372 int rc;
1373 char str[sizeof ("required")];
1374
1375 rc = smb_config_getstr(id, str, sizeof (str));
1376 if (rc != SMBD_SMF_OK)
1377 return (SMB_CONFIG_DISABLED);
1378
1379 if (strncmp(str, "required", sizeof (str)) == 0)
1380 return (SMB_CONFIG_REQUIRED);
1381 if (strncmp(str, "enabled", sizeof (str)) == 0)
1382 return (SMB_CONFIG_ENABLED);
1383
1384 return (SMB_CONFIG_DISABLED);
1385 }
|