r24630: Store Samba configuratin options only under the default name, not as aliases.
authorMichael Adam <obnox@samba.org>
Wed, 22 Aug 2007 16:03:17 +0000 (16:03 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:30:12 +0000 (12:30 -0500)
This prevents creation of problematic configurations from registry editors
like regedit or "net rpc registry".

I will refactor the code to be somewhat more concise,
but I wanted to have this in the tree, now I got it working... :-)

Michael
(This used to be commit 4424a030324ab646a025b50fcb89e1b5cdfcbbe8)

source3/registry/reg_smbconf.c

index 2a7f10cc2745e202a29534ea98f05e1dff8bbc68..a809f6b6437b21f38e2a65b04e5533a3d0d5d636 100644 (file)
@@ -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,