Print this page
NEX-19857 ads_site broken in sharectl get/set smb
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-17523 Enable SMB3 server by default
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10019 SMB server min_protocol setting
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-2314 SMB server debug logging needs improvement
NEX-1852 re-enable Kerberos-style AD join (try 2)
NEX-1638 Updated DC Locator
 Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
NEX-1050 enable_smb2 should be smb2_enable
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-56 extended security NTLMSSP, inbound
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SFR-56 Identity Management for UNIX (IDMU) authentication support
re #6813 rb1757 port 2976 Child folder visibility through shares

*** 18,28 **** * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* * CIFS configuration management library */ --- 18,28 ---- * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * CIFS configuration management library */
*** 64,73 **** --- 64,74 ---- #define IDMAP_FMRI_PREFIX "system/idmap" #define MACHINE_SID "machine_sid" #define MACHINE_UUID "machine_uuid" #define IDMAP_DOMAIN "domain_name" #define IDMAP_PREF_DC "preferred_dc" + #define IDMAP_SITE_NAME "site_name" #define IDMAP_PG_NAME "config" #define SMB_SECMODE_WORKGRP_STR "workgroup" #define SMB_SECMODE_DOMAIN_STR "domain"
*** 143,164 **** --- 144,204 ---- {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0}, {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0}, {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0}, {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0}, {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0}, + {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0}, + {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0}, + {SMB_CI_BYPASS_TRAVERSE_CHECKING, + "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0}, /* SMB_CI_MAX */ }; + /* + * We store the max SMB protocol version in SMF as a string, + * (for convenience of svccfg etc) but the programmatic get/set + * interfaces use the numeric form. + * + * The numeric values are as defined in the [MS-SMB2] spec. + * except for how we represent "1" (for SMB1) which is an + * arbitrary value below SMB2_VERS_BASE. + */ + static struct str_val + smb_versions[] = { + { "3.02", SMB_VERS_3_02 }, + { "3.0", SMB_VERS_3_0 }, + { "2.1", SMB_VERS_2_1 }, + { "2.002", SMB_VERS_2_002 }, + { "1", SMB_VERS_1 }, + { NULL, 0 } + }; + static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t); static boolean_t smb_is_base64(unsigned char c); static char *smb_base64_encode(char *str_to_encode); static char *smb_base64_decode(char *encoded_str); static int smb_config_get_idmap_preferred_dc(char *, int); static int smb_config_set_idmap_preferred_dc(char *); + static int smb_config_get_idmap_site_name(char *, int); + static int smb_config_set_idmap_site_name(char *); + static uint32_t + smb_convert_version_str(const char *version) + { + uint32_t dialect = 0; + int i; + + for (i = 0; smb_versions[i].str != NULL; i++) { + if (strcmp(version, smb_versions[i].str) == 0) + dialect = smb_versions[i].val; + } + + return (dialect); + } + char * smb_config_getname(smb_cfg_id_t id) { smb_cfg_param_t *cfg; cfg = smb_config_getent(id);
*** 375,384 **** --- 415,426 ---- *cbuf = '\0'; cfg = smb_config_getent(id); assert(cfg->sc_type == SCF_TYPE_ASTRING); + if (id == SMB_CI_ADS_SITE) + return (smb_config_get_idmap_site_name(cbuf, bufsz)); if (id == SMB_CI_DOMAIN_SRV) return (smb_config_get_idmap_preferred_dc(cbuf, bufsz)); handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); if (handle == NULL)
*** 581,590 **** --- 623,634 ---- char *pg; cfg = smb_config_getent(id); assert(cfg->sc_type == SCF_TYPE_ASTRING); + if (id == SMB_CI_ADS_SITE) + return (smb_config_set_idmap_site_name(value)); if (id == SMB_CI_DOMAIN_SRV) return (smb_config_set_idmap_preferred_dc(value)); protected = B_FALSE;
*** 622,632 **** --- 666,718 ---- } value = tmp; } + /* + * We don't want people who care enough about protecting their data + * by requiring encryption to accidentally expose their data + * by lowering the protocol, so prevent them from going below 3.0 + * if encryption is required. + * Also, ensure that max_protocol >= min_protocol. + */ + if (id == SMB_CI_MAX_PROTOCOL) { + smb_cfg_val_t encrypt; + uint32_t min; + uint32_t val; + + encrypt = smb_config_get_require(SMB_CI_ENCRYPT); + min = smb_config_get_min_protocol(); + val = smb_convert_version_str(value); + + if (encrypt == SMB_CONFIG_REQUIRED && + val < SMB_VERS_3_0) { + syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0" + " while smbd/encrypt == required."); + rc = SMBD_SMF_INVALID_ARG; + } else if (val < min) { + syslog(LOG_ERR, "Cannot set smbd/max_protocol to less" + " than smbd/min_protocol."); + rc = SMBD_SMF_INVALID_ARG; + } + } else if (id == SMB_CI_MIN_PROTOCOL) { + uint32_t max; + uint32_t val; + + max = smb_config_get_max_protocol(); + val = smb_convert_version_str(value); + + if (val > max) { + syslog(LOG_ERR, "Cannot set smbd/min_protocol to more" + " than smbd/max_protocol."); + rc = SMBD_SMF_INVALID_ARG; + } + } + + if (rc == SMBD_SMF_OK) { rc = smb_smf_set_string_property(handle, cfg->sc_name, value); + } free(tmp); (void) smb_smf_end_transaction(handle); smb_smf_scf_fini(handle); return (rc);
*** 875,884 **** --- 961,994 ---- { return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, IDMAP_PREF_DC, value)); } + static int + smb_config_get_idmap_site_name(char *cbuf, int bufsz) + { + char *s; + int len, rc = -1; + + s = smb_config_getenv_generic(IDMAP_SITE_NAME, + IDMAP_FMRI_PREFIX, IDMAP_PG_NAME); + if (s != NULL) { + len = strlcpy(cbuf, s, bufsz); + if (len < bufsz) + rc = 0; + free(s); + } + return (rc); + } + + static int + smb_config_set_idmap_site_name(char *value) + { + return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, + IDMAP_SITE_NAME, value)); + } + /* * smb_config_set_idmap_domain * * Set the "config/domain_name" parameter from IDMAP SMF repository. */
*** 1085,1148 **** assert(0); return (NULL); } /* ! * We store the max SMB protocol version in SMF as a string, ! * (for convenience of svccfg etc) but the programmatic get/set ! * interfaces use the numeric form. ! * ! * The numeric values are as defined in the [MS-SMB2] spec. ! * except for how we represent "1" (for SMB1) which is an ! * arbitrary value below SMB2_VERS_BASE. */ ! static struct str_val ! smb_versions[] = { ! { "3.0", SMB_VERS_3_0 }, ! { "2.1", SMB_VERS_2_1 }, ! { "2.002", SMB_VERS_2_002 }, ! { "1", SMB_VERS_1 }, ! { NULL, 0 } ! }; /* ! * This really should be the latest (SMB_VERS_3_0) ! * but we're being cautious with SMB3 for a while. */ ! uint32_t max_protocol_default = SMB_VERS_2_1; uint32_t ! smb_config_get_max_protocol(void) { ! char str[SMB_VERSTR_LEN]; ! int i, rc; ! rc = smb_config_getstr(SMB_CI_MAX_PROTOCOL, str, sizeof (str)); ! if (rc == SMBD_SMF_OK) { ! for (i = 0; smb_versions[i].str != NULL; i++) { ! if (strcmp(str, smb_versions[i].str) == 0) ! return (smb_versions[i].val); ! } ! if (str[0] != '\0') { ! syslog(LOG_ERR, "smbd/max_protocol value invalid"); ! } ! } ! return (max_protocol_default); } int smb_config_check_protocol(char *value) { ! int i; ! ! for (i = 0; smb_versions[i].str != NULL; i++) { ! if (strcmp(value, smb_versions[i].str) == 0) return (0); - } return (-1); } /* --- 1195,1265 ---- assert(0); return (NULL); } + static uint32_t + smb_config_get_protocol(smb_cfg_id_t id, char *name, uint32_t default_val) + { + char str[SMB_VERSTR_LEN]; + int rc; + uint32_t val; + rc = smb_config_getstr(id, str, sizeof (str)); + if (rc == SMBD_SMF_OK) { + val = smb_convert_version_str(str); + if (val != 0) + return (val); + if (str[0] != '\0') { + syslog(LOG_ERR, "smbd/%s value invalid: %s", name, str); + } + } + + return (default_val); + } + /* ! * The service manifest has empty values by default for min_protocol and ! * max_protocol. The expectation is that when those values are empty, we don't ! * constrain the range of supported protocol versions (and allow use of the ! * whole range that we implement). For that reason, this should usually be the ! * highest protocol version we implement. */ ! uint32_t max_protocol_default = SMB_VERS_3_02; + uint32_t + smb_config_get_max_protocol(void) + { + uint32_t max; + + max = smb_config_get_protocol(SMB_CI_MAX_PROTOCOL, "max_protocol", + max_protocol_default); + + return (max); + } + /* ! * This should eventually be SMB_VERS_2_BASE */ ! uint32_t min_protocol_default = SMB_VERS_1; uint32_t ! smb_config_get_min_protocol(void) { ! uint32_t min; ! min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol", ! min_protocol_default); ! return (min); } int smb_config_check_protocol(char *value) { ! if (smb_convert_version_str(value) != 0) return (0); return (-1); } /*
*** 1245,1250 **** --- 1362,1385 ---- */ void smb_config_upgrade(void) { upgrade_smb2_enable(); + } + + smb_cfg_val_t + smb_config_get_require(smb_cfg_id_t id) + { + int rc; + char str[sizeof ("required")]; + + rc = smb_config_getstr(id, str, sizeof (str)); + if (rc != SMBD_SMF_OK) + return (SMB_CONFIG_DISABLED); + + if (strncmp(str, "required", sizeof (str)) == 0) + return (SMB_CONFIG_REQUIRED); + if (strncmp(str, "enabled", sizeof (str)) == 0) + return (SMB_CONFIG_ENABLED); + + return (SMB_CONFIG_DISABLED); }