diff options
author | Gordon Ross <gwr@racktopsystems.com> | 2022-03-12 10:52:24 -0500 |
---|---|---|
committer | Toomas Soome <tsoome@me.com> | 2022-09-26 17:46:46 +0300 |
commit | 76b0ca5a9552055cbe0fc7faabd3269bf63c4060 (patch) | |
tree | cf109688d38224409187eadbd959e49073d1cf4c | |
parent | 2b766db42fbe7dc313c8d6de18e15f3aa15a35bb (diff) | |
download | illumos-joyent-76b0ca5a9552055cbe0fc7faabd3269bf63c4060.tar.gz |
15001 Unable to set smb property max_protocol to 3.1.1 or empty
Reviewed-by: Jerry Jelinek <gjelinek@racktopsystems.com>
Reviewed by: Albert Lee <alee@racktopsystems.com>
Reviewed-by: Jim Johnson <jjohnson@racktopsystems.com>
Reviewed by: Joyce McIntosh <jmcintosh@racktopsystems.com>
Reviewed by: Matt Barden <mbarden@tintri.com>
Approved by: Dan McDonald <danmcd@mnx.io>
-rw-r--r-- | usr/src/lib/libshare/smb/libshare_smb.c | 150 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/libsmb.h | 2 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/mapfile-vers | 3 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/smb_cfg.c | 157 |
4 files changed, 108 insertions, 204 deletions
diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index da14ea94c3..b926637def 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -890,12 +890,12 @@ struct smb_proto_option_defs { SMB_REFRESH_REFRESH }, { SMB_CI_DISPOSITION, 0, MAX_VALUE_BUFLEN, disposition_validator, SMB_REFRESH_REFRESH }, + { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator, + SMB_REFRESH_REFRESH }, { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator, SMB_REFRESH_REFRESH }, { SMB_CI_ENCRYPT, 0, MAX_VALUE_BUFLEN, require_validator, SMB_REFRESH_REFRESH }, - { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator, - SMB_REFRESH_REFRESH }, { SMB_CI_BYPASS_TRAVERSE_CHECKING, 0, 0, true_false_validator, SMB_REFRESH_REFRESH }, { SMB_CI_OPLOCK_ENABLE, 0, 0, true_false_validator, @@ -1490,27 +1490,6 @@ smb_enable_service(void) } /* - * smb_validate_proto_prop(index, name, value) - * - * Verify that the property specified by name can take the new - * value. This is a sanity check to prevent bad values getting into - * the default files. - */ -static int -smb_validate_proto_prop(int index, char *name, char *value) -{ - if ((name == NULL) || (index < 0)) - return (SA_BAD_VALUE); - - if (smb_proto_options[index].validator == NULL) - return (SA_OK); - - if (smb_proto_options[index].validator(index, value) == SA_OK) - return (SA_OK); - return (SA_BAD_VALUE); -} - -/* * smb_set_proto_prop(prop) * * check that prop is valid. @@ -1527,35 +1506,50 @@ smb_set_proto_prop(sa_property_t prop) name = sa_get_property_attr(prop, "type"); value = sa_get_property_attr(prop, "value"); - if (name != NULL && value != NULL) { - index = findprotoopt(name); - if (index >= 0) { - /* should test for valid value */ - ret = smb_validate_proto_prop(index, name, value); - if (ret == SA_OK) { - opt = &smb_proto_options[index]; - - /* Save to SMF */ - if (smb_config_set(opt->smb_index, - value) != 0) { - ret = SA_BAD_VALUE; - goto out; - } - /* - * Specialized refresh mechanisms can - * be flagged in the proto_options and - * processed here. - */ - if (opt->refresh & SMB_REFRESH_REFRESH) - (void) smf_refresh_instance( - SMBD_DEFAULT_INSTANCE_FMRI); - else if (opt->refresh & SMB_REFRESH_RESTART) - (void) smf_restart_instance( - SMBD_DEFAULT_INSTANCE_FMRI); - } - } + if (name == NULL || value == NULL) { + ret = SA_NO_SUCH_PROP; + goto out; + } + + index = findprotoopt(name); + if (index < 0) { + ret = SA_NO_SUCH_PROP; + goto out; + } + opt = &smb_proto_options[index]; + + /* + * When setting max_protocol or min_protocol, + * allow"3.1.1" as an alias for "3.11". + */ + if (opt->smb_index == SMB_CI_MAX_PROTOCOL || + opt->smb_index == SMB_CI_MIN_PROTOCOL) + if (strcmp(value, "3.1.1") == 0) + strcpy(value, "3.11"); + + /* Test for valid value */ + if (opt->validator != NULL && + (ret = opt->validator(index, value)) != SA_OK) + goto out; + + /* Save to SMF */ + if (smb_config_set(opt->smb_index, value) != 0) { + ret = SA_BAD_VALUE; + goto out; } + /* + * Specialized refresh mechanisms can + * be flagged in the proto_options and + * processed here. + */ + if (opt->refresh & SMB_REFRESH_REFRESH) + (void) smf_refresh_instance( + SMBD_DEFAULT_INSTANCE_FMRI); + else if (opt->refresh & SMB_REFRESH_RESTART) + (void) smf_restart_instance( + SMBD_DEFAULT_INSTANCE_FMRI); + out: if (name != NULL) sa_free_attr_string(name); @@ -2366,21 +2360,69 @@ disposition_validator(int index, char *value) return (SA_BAD_VALUE); } -/*ARGSUSED*/ static int protocol_validator(int index, char *value) { + struct smb_proto_option_defs *opt; + smb_cfg_val_t encrypt; + uint32_t max; + uint32_t min; + uint32_t val; + if (value == NULL) return (SA_BAD_VALUE); + /* Allow setting back to empty (use defaults) */ if (*value == '\0') return (SA_OK); - if (smb_config_check_protocol(value) == 0) - return (SA_OK); + val = smb_convert_version_str(value); + if (val == 0) + return (SA_BAD_VALUE); - return (SA_BAD_VALUE); + /* + * We don't want people who care enough about protecting their data + * by requiring encryption to accidentally expose their data by + * lowering the max protocol, so prevent them from going below 3.0 + * if encryption is required. + * Also, ensure that max_protocol >= min_protocol. + */ + opt = &smb_proto_options[index]; + switch (opt->smb_index) { + case SMB_CI_MAX_PROTOCOL: + + encrypt = smb_config_get_require(SMB_CI_ENCRYPT); + 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."); + return (SA_VALUE_CONFLICT); + } + min = smb_config_get_min_protocol(); + if (val < min) { + syslog(LOG_ERR, "Cannot set smbd/max_protocol to less" + " than smbd/min_protocol."); + return (SA_VALUE_CONFLICT); + } + break; + + case SMB_CI_MIN_PROTOCOL: + + max = smb_config_get_max_protocol(); + if (val > max) { + syslog(LOG_ERR, "Cannot set smbd/min_protocol to more" + " than smbd/max_protocol."); + return (SA_VALUE_CONFLICT); + } + break; + + default: + syslog(LOG_ERR, "Unexpected smb protocol validator index %d", + opt->smb_index); + return (SA_BAD_VALUE); + } + + return (SA_OK); } /* diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 5b6a41cbf0..48336f2d73 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -220,9 +220,9 @@ extern void smb_config_get_version(smb_version_t *); uint32_t smb_config_get_execinfo(char *, char *, size_t); extern void smb_config_get_negtok(uchar_t *, uint32_t *); -extern int smb_config_check_protocol(char *); extern uint32_t smb_config_get_max_protocol(void); extern uint32_t smb_config_get_min_protocol(void); +extern uint32_t smb_convert_version_str(const char *); extern void smb_config_upgrade(void); extern uint16_t smb31_config_get_encrypt_cipher(void); diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index ddb0698522..9cb89eb509 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -98,13 +98,13 @@ SYMBOL_VERSION SUNWprivate { smb_codepage_init; smb_common_decode; smb_common_encode; - smb_config_check_protocol; smb_config_get; smb_config_get_ads_enable; smb_config_get_debug; smb_config_get_execinfo; smb_config_get_fg_flag; smb_config_get_localsid; + smb_config_get_require; smb_config_get_secmode; smb_config_get_version; smb_config_getbool; @@ -124,6 +124,7 @@ SYMBOL_VERSION SUNWprivate { smb_config_setnum; smb_config_setstr; smb_config_upgrade; + smb_convert_version_str; smb_crc_gen; smb_ctxbuf_init; smb_ctxbuf_len; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index 160629e2ed..88890f4f8c 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -28,6 +28,13 @@ * CIFS configuration management library */ +/* + * Checking for things like unsupportable parameter combinations are + * the responsibility of callers of these functions. Example include: + * trying to set min_protocol above max_protocol, or requiring encryption + * with an allowed protocol range that can't support it. + */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -198,7 +205,7 @@ 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 +uint32_t smb_convert_version_str(const char *version) { uint32_t dialect = 0; @@ -683,49 +690,7 @@ smb_config_setstr(smb_cfg_id_t id, char *value) 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); - } + rc = smb_smf_set_string_property(handle, cfg->sc_name, value); free(tmp); (void) smb_smf_end_transaction(handle); @@ -1268,15 +1233,6 @@ smb_config_get_min_protocol(void) return (min); } -int -smb_config_check_protocol(char *value) -{ - if (smb_convert_version_str(value) != 0) - return (0); - - return (-1); -} - /* * Only SMB 3.x supports encryption. * SMB 3.0.2 uses AES128-CCM only. @@ -1323,100 +1279,6 @@ smb31_config_get_encrypt_cipher(void) return (cipher); } -/* - * If smb2_enable is present and max_protocol is empty, - * set max_protocol. Delete smb2_enable. - */ -static void -upgrade_smb2_enable() -{ - smb_scfhandle_t *handle; - char *s2e_name = "smb2_enable"; - char *s2e_sval; - uint8_t s2e_bval; - char *maxp_name = "max_protocol"; - char *maxp_sval; - char verstr[SMB_VERSTR_LEN]; - int rc; - - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) - return; - rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); - if (rc != SMBD_SMF_OK) - goto out; - - /* Is there an "smb2_enable" property? */ - rc = smb_smf_get_boolean_property(handle, s2e_name, &s2e_bval); - if (rc != SMBD_SMF_OK) { - syslog(LOG_DEBUG, "upgrade: smb2_enable not found"); - goto out; - } - - /* - * We will try to delete the smb2_enable property, so we need - * the transaction to start now, before we modify max_protocol - */ - if ((rc = smb_smf_start_transaction(handle)) != 0) { - syslog(LOG_DEBUG, "upgrade_smb2_enable: start trans (%d)", rc); - goto out; - } - - /* - * Old (smb2_enable) property exists. - * Does the new one? (max_protocol) - */ - rc = smb_smf_get_string_property(handle, maxp_name, - verstr, sizeof (verstr)); - if (rc == SMBD_SMF_OK && !smb_config_check_protocol(verstr)) { - syslog(LOG_DEBUG, "upgrade: found %s = %s", - maxp_name, verstr); - /* Leave existing max_protocol as we found it. */ - } else { - /* - * New property missing or invalid. - * Upgrade from "smb2_enable". - */ - if (s2e_bval == 0) { - s2e_sval = "false"; - maxp_sval = "1"; - } else { - s2e_sval = "true"; - maxp_sval = "2.1"; - } - /* - * Note: Need this in the same transaction as the - * delete of smb2_enable below. - */ - rc = smb_smf_set_string_property(handle, maxp_name, maxp_sval); - if (rc != SMBD_SMF_OK) { - syslog(LOG_ERR, "failed to set smbd/%d (%d)", - maxp_name, rc); - goto out; - } - syslog(LOG_INFO, "upgrade smbd/smb2_enable=%s " - "converted to smbd/max_protocol=%s", - s2e_sval, maxp_sval); - } - - /* - * Delete the old smb2_enable property. - */ - if ((rc = smb_smf_delete_property(handle, s2e_name)) != 0) { - syslog(LOG_DEBUG, "upgrade_smb2_enable: delete prop (%d)", rc); - } else if ((rc = smb_smf_end_transaction(handle)) != 0) { - syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc); - } - if (rc != 0) { - syslog(LOG_ERR, "failed to delete property smbd/%d (%d)", - s2e_name, rc); - } - -out: - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); -} - /* * Run once at startup convert old SMF settings to current. @@ -1424,7 +1286,6 @@ out: void smb_config_upgrade(void) { - upgrade_smb2_enable(); } smb_cfg_val_t |