Print this page
12513 SMB 3.1.1 support for server


   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>


 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         }


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 
1281         handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
1282         if (handle == NULL)




   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>


 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         }


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)