summaryrefslogtreecommitdiff
path: root/source3/registry
diff options
context:
space:
mode:
Diffstat (limited to 'source3/registry')
-rw-r--r--source3/registry/reg_smbconf.c155
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,