From: "Leonidas P. Papadakos" <papadakospan@xxxxxxxxx> Local options in share groups override global ones. Signed-off-by: Leonidas P. Papadakos <papadakospan@xxxxxxxxx> Signed-off-by: Namjae Jeon <linkinjeon@xxxxxxxxxx> --- lib/config_parser.c | 119 +++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/lib/config_parser.c b/lib/config_parser.c index aa1dbf2..9ce730c 100644 --- a/lib/config_parser.c +++ b/lib/config_parser.c @@ -21,6 +21,7 @@ struct smbconf_global global_conf; struct smbconf_parser parser; +struct smbconf_group *global_group; unsigned long long memparse(const char *v) { @@ -389,62 +390,62 @@ static int cp_add_global_guest_account(gpointer _v) return 0; } -static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) +static gboolean global_group_kv(gpointer _k, gpointer _v, gpointer user_data) { if (!cp_key_cmp(_k, "server string")) { global_conf.server_string = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "workgroup")) { global_conf.work_group = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "netbios name")) { global_conf.netbios_name = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "server min protocol")) { global_conf.server_min_protocol = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "server signing")) { global_conf.server_signing = cp_get_group_kv_config_opt(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "server max protocol")) { global_conf.server_max_protocol = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "guest account")) { cp_add_global_guest_account(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "max active sessions")) { global_conf.sessions_cap = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "tcp port")) { if (!global_conf.tcp_port) global_conf.tcp_port = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "ipc timeout")) { global_conf.ipc_timeout = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "max open files")) { global_conf.file_max = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "restrict anonymous")) { @@ -455,7 +456,7 @@ static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) pr_err("Invalid restrict anonymous value\n"); } - return; + return TRUE; } if (!cp_key_cmp(_k, "map to guest")) { @@ -469,22 +470,22 @@ static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) if (!cp_key_cmp(_v, "bad uid")) global_conf.map_to_guest = KSMBD_CONF_MAP_TO_GUEST_BAD_UID; - return; + return TRUE; } if (!cp_key_cmp(_k, "bind interfaces only")) { global_conf.bind_interfaces_only = cp_get_group_kv_bool(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "interfaces")) { global_conf.interfaces = cp_get_group_kv_list(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "deadtime")) { global_conf.deadtime = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "smb2 leases")) { @@ -493,27 +494,27 @@ static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) else global_conf.flags &= ~KSMBD_GLOBAL_FLAG_SMB2_LEASES; - return; + return TRUE; } if (!cp_key_cmp(_k, "root directory")) { global_conf.root_dir = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "smb2 max read")) { global_conf.smb2_max_read = memparse(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "smb2 max write")) { global_conf.smb2_max_write = memparse(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "smb2 max trans")) { global_conf.smb2_max_trans = memparse(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "smb3 encryption")) { @@ -522,22 +523,22 @@ static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) else global_conf.flags &= ~KSMBD_GLOBAL_FLAG_SMB3_ENCRYPTION; - return; + return TRUE; } if (!cp_key_cmp(_k, "share:fake_fscaps")) { global_conf.share_fake_fscaps = cp_get_group_kv_long(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "kerberos service name")) { global_conf.krb5_service_name = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "kerberos keytab file")) { global_conf.krb5_keytab_file = cp_get_group_kv_string(_v); - return; + return TRUE; } if (!cp_key_cmp(_k, "server multi channel support")) { @@ -546,16 +547,35 @@ static void global_group_kv(gpointer _k, gpointer _v, gpointer user_data) else global_conf.flags &= ~KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL; - return; + return TRUE; } if (!cp_key_cmp(_k, "smb2 max credits")) { global_conf.smb2_max_credits = memparse(_v); - return; + return TRUE; } + + /* At this point, this is an option that must be applied to all shares */ + return FALSE; +} + +static void global_conf_default(void) +{ + /* The SPARSE_FILES file system capability flag is set by default */ + global_conf.share_fake_fscaps = 64; +} + +static void global_conf_create(void) +{ + /* + * This will transfer server options to global_conf, and leave behind + * in the global parser group, the options that must be applied to every + * share + */ + g_hash_table_foreach_remove(global_group->kv, global_group_kv, NULL); } -static void fixup_missing_global_group(void) +static void global_conf_fixup_missing(void) { int ret; @@ -593,29 +613,30 @@ static void fixup_missing_global_group(void) ret); } -static void default_global_group(void) +static void append_key_value(gpointer _k, gpointer _v, gpointer user_data) { - /* The SPARSE_FILES file system capability flag is set by default */ - global_conf.share_fake_fscaps = 64; -} + GHashTable *receiver = (GHashTable *) user_data; -static void global_group(struct smbconf_group *group) -{ - g_hash_table_foreach(group->kv, global_group_kv, NULL); + /* Don't override local share options */ + if (!g_hash_table_lookup(receiver, _k)) + g_hash_table_insert(receiver, g_strdup(_k), g_strdup(_v)); } #define GROUPS_CALLBACK_STARTUP_INIT 0x1 #define GROUPS_CALLBACK_REINIT 0x2 -static void groups_callback(gpointer _k, gpointer _v, gpointer flags) +static void groups_callback(gpointer _k, gpointer _v, gpointer user_data) { - if (g_ascii_strncasecmp(_k, "global", 6)) { - shm_add_new_share((struct smbconf_group *)_v); - return; - } + struct smbconf_group *group = (struct smbconf_group *)_v; + + if (group != global_group) { + if (global_group && g_ascii_strncasecmp(_k, "ipc$", 4)) + g_hash_table_foreach(global_group->kv, + append_key_value, + group->kv); - if (flags == (gpointer)GROUPS_CALLBACK_STARTUP_INIT) - global_group((struct smbconf_group *)_v); + shm_add_new_share(group); + } } static int cp_add_ipc_share(void) @@ -648,7 +669,7 @@ static int __cp_parse_smbconfig(const char *smbconf, GHFunc cb, long flags) { int ret; - default_global_group(); + global_conf_default(); ret = cp_smbconfig_hash_create(smbconf); if (ret) @@ -656,10 +677,16 @@ static int __cp_parse_smbconfig(const char *smbconf, GHFunc cb, long flags) ret = cp_add_ipc_share(); if (!ret) { + global_group = g_hash_table_lookup(parser.groups, "global"); + + if (global_group && (flags == GROUPS_CALLBACK_STARTUP_INIT)) + global_conf_create(); + g_hash_table_foreach(parser.groups, groups_callback, - (gpointer)flags); - fixup_missing_global_group(); + NULL); + + global_conf_fixup_missing(); } cp_smbconfig_destroy(); return ret; -- 2.25.1