diff options
Diffstat (limited to 'source3/registry')
-rw-r--r-- | source3/registry/reg_smbconf.c | 155 |
1 files changed, 152 insertions, 3 deletions
diff --git a/source3/registry/reg_smbconf.c b/source3/registry/reg_smbconf.c index 2a7f10cc27..a809f6b643 100644 --- a/source3/registry/reg_smbconf.c +++ b/source3/registry/reg_smbconf.c @@ -43,18 +43,167 @@ static BOOL smbconf_store_values( const char *key, REGVAL_CTR *val ) { int i; int num_values = regval_ctr_numvals(val); + REGVAL_CTR *new_val_ctr; + + /* + * we build a second regval container and copy over the values, + * possibly changing names to the canonical name, because when + * canonicalizing parameter names and replacing the original parameter + * (with reval_ctr_deletevalue and regval_ctr_addvalue) in the original + * container, the order would change and that is not so good in the + * "for" loop... :-o + */ + new_val_ctr = TALLOC_ZERO_P(val, REGVAL_CTR); + if (new_val_ctr == NULL) { + DEBUG(1, ("out of memory\n")); + return False; + } for (i=0; i < num_values; i++) { REGISTRY_VALUE *theval = regval_ctr_specific_value(val, i); const char *valname = regval_name(theval); + int res; - if (registry_smbconf_valname_forbidden(valname)) { - DEBUG(0, ("smbconf_store_values: value '%s' forbidden " + DEBUG(10, ("inspecting value '%s'\n", valname)); + + /* unfortunately, we can not reject names that are not + * valid parameter names here, since e.g. regedit first + * creates values as "New Value #1" and so on and then + * drops into rename. */ + + if (regval_type(theval) != REG_SZ) { + DEBUG(1, ("smbconf_store_values: only registry value " + "type REG_SZ currently allowed under key " + "smbconf\n")); + return False; + } + + if (registry_smbconf_valname_forbidden(regval_name(theval))) { + DEBUG(1, ("smbconf_store_values: value '%s' forbidden " "in registry.\n", valname)); return False; } + + if (lp_parameter_is_valid(valname) && + !lp_parameter_is_canonical(valname)) + { + char *valstr; + size_t len; + const char *canon_valname; + const char *canon_valstr; + BOOL inverse; + struct registry_value *value; + WERROR err; + DATA_BLOB value_data; + TALLOC_CTX *mem_ctx; + + DEBUG(5, ("valid parameter '%s' given but it is a " + "synonym. going to canonicalize it.\n", + valname)); + + mem_ctx = talloc_new(val); + if (mem_ctx == NULL) { + DEBUG(1, ("out of memory...\n")); + return False; + } + + err = registry_pull_value(mem_ctx, &value, + theval->type, + theval->data_p, + theval->size, + theval->size); + if (!W_ERROR_IS_OK(err)) { + TALLOC_FREE(mem_ctx); + return False; + } + + valstr = (value->v.sz.str); + len = value->v.sz.len; + DEBUG(10, ("theval->size: %d, value->v.sz.len: %d, " + "value->v.sz.str: '%s'\n", + theval->size, value->v.sz.len, + value->v.sz.str)); + if (valstr[len - 1] != '\0') { + DEBUG(10, ("string is not '\\0'-terminated. " + "adding '\\0'...\n")); + valstr = TALLOC_REALLOC_ARRAY(mem_ctx, valstr, + char, len + 1); + if (valstr == NULL) { + DEBUG(1, ("out of memory\n")); + TALLOC_FREE(mem_ctx); + return False; + } + valstr[len] = '\0'; + len++; + } + + if (!lp_canonicalize_parameter(valname, &canon_valname, + &inverse)) + { + DEBUG(5, ("oops: lp_canonicalize_parameter " + "failed after lp_parameter_is_valid. " + "This should not happen!\n")); + TALLOC_FREE(mem_ctx); + return False; + } + DEBUG(10, ("old value name: '%s', canonical value " + "name: '%s'\n", valname, canon_valname)); + if (inverse && lp_string_is_valid_boolean(valstr)) { + lp_invert_boolean(valstr, &canon_valstr); + } else { + canon_valstr = valstr; + } + + ZERO_STRUCTP(value); + + value->type = REG_SZ; + value->v.sz.str = CONST_DISCARD(char *, canon_valstr); + value->v.sz.len = strlen(canon_valstr) + 1; + + DEBUG(10, ("NEW: value->type: %d, value->v.sz.len: %d, " + "value->v.sz.str: '%s'\n", value->type, + value->v.sz.len, value->v.sz.str)); + + err = registry_push_value(mem_ctx, value, &value_data); + if (!W_ERROR_IS_OK(err)) { + DEBUG(10, ("error calling registry_push_value." + "\n")); + TALLOC_FREE(mem_ctx); + return False; + } + + DEBUG(10, ("adding canonicalized parameter to " + "container.\n")); + res = regval_ctr_addvalue(new_val_ctr, canon_valname, + value->type, + (char *)value_data.data, + value_data.length); + if (res == 0) { + DEBUG(10, ("error calling regval_ctr_addvalue. " + "(no memory?)\n")); + TALLOC_FREE(mem_ctx); + return False; + } + DEBUG(10, ("parameter added. container now has %d " + "values.\n", res)); + + TALLOC_FREE(mem_ctx); + } else { + DEBUG(10, ("%s parameter found, " + "copying it to new container...\n", + (lp_parameter_is_valid(valname)? + "valid":"unknown"))); + res = regval_ctr_copyvalue(new_val_ctr, theval); + if (res == 0) { + DEBUG(10, ("error calling regval_ctr_copyvalue." + " (no memory?)\n")); + return False; + } + DEBUG(10, ("parameter copied. container now has %d " + "values.\n", res)); + } } - return regdb_ops.store_values(key, val); + return regdb_ops.store_values(key, new_val_ctr); } static BOOL smbconf_reg_access_check(const char *keyname, uint32 requested, |