r24996: Eliminate more trailing spaces...
[ira/wip.git] / source3 / registry / reg_smbconf.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Volker Lendecke 2006
5  *  Copyright (C) Michael Adam 2007
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_RPC_SRV
25
26 extern REGISTRY_OPS regdb_ops;          /* these are the default */
27
28 static int smbconf_fetch_keys( const char *key, REGSUBKEY_CTR *subkey_ctr )
29 {
30         return regdb_ops.fetch_subkeys(key, subkey_ctr);
31 }
32
33 static BOOL smbconf_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
34 {
35         return regdb_ops.store_subkeys(key, subkeys);
36 }
37
38 static int smbconf_fetch_values( const char *key, REGVAL_CTR *val )
39 {
40         return regdb_ops.fetch_values(key, val);
41 }
42
43 static BOOL smbconf_store_values( const char *key, REGVAL_CTR *val )
44 {
45         int i;
46         int num_values = regval_ctr_numvals(val);
47         REGVAL_CTR *new_val_ctr;
48
49         /*
50          * we build a second regval container and copy over the values,
51          * possibly changing names to the canonical name, because when
52          * canonicalizing parameter names and replacing the original parameter
53          * (with reval_ctr_deletevalue and regval_ctr_addvalue) in the original
54          * container, the order would change and that is not so good in the
55          * "for" loop...  :-o
56          */
57         new_val_ctr = TALLOC_ZERO_P(val, REGVAL_CTR);
58         if (new_val_ctr == NULL) {
59                 DEBUG(1, ("out of memory\n"));
60                 return False;
61         }
62
63         for (i=0; i < num_values; i++) {
64                 REGISTRY_VALUE *theval = regval_ctr_specific_value(val, i);
65                 const char *valname = regval_name(theval);
66                 int res;
67
68                 DEBUG(10, ("inspecting value '%s'\n", valname));
69
70                 /* unfortunately, we can not reject names that are not
71                  * valid parameter names here, since e.g. regedit first
72                  * creates values as "New Value #1" and so on and then
73                  * drops into rename. */
74
75                 if (regval_type(theval) != REG_SZ) {
76                         DEBUG(1, ("smbconf_store_values: only registry value "
77                               "type REG_SZ currently allowed under key "
78                               "smbconf\n"));
79                         return False;
80                 }
81
82                 if (registry_smbconf_valname_forbidden(regval_name(theval))) {
83                         DEBUG(1, ("smbconf_store_values: value '%s' forbidden "
84                               "in registry.\n", valname));
85                         return False;
86                 }
87
88                 if (lp_parameter_is_valid(valname) &&
89                     !lp_parameter_is_canonical(valname))
90                 {
91                         char *valstr;
92                         size_t len;
93                         const char *canon_valname;
94                         const char *canon_valstr;
95                         BOOL inverse;
96                         struct registry_value *value;
97                         WERROR err;
98                         DATA_BLOB value_data;
99                         TALLOC_CTX *mem_ctx;
100
101                         DEBUG(5, ("valid parameter '%s' given but it is a "
102                                   "synonym. going to canonicalize it.\n",
103                                   valname));
104
105                         mem_ctx = talloc_new(val);
106                         if (mem_ctx == NULL) {
107                                 DEBUG(1, ("out of memory...\n"));
108                                 return False;
109                         }
110
111                         err = registry_pull_value(mem_ctx, &value,
112                                                   theval->type,
113                                                   theval->data_p,
114                                                   theval->size,
115                                                   theval->size);
116                         if (!W_ERROR_IS_OK(err)) {
117                                 TALLOC_FREE(mem_ctx);
118                                 return False;
119                         }
120
121                         valstr = (value->v.sz.str);
122                         len = value->v.sz.len;
123                         if (valstr[len - 1] != '\0') {
124                                 DEBUG(10, ("string is not '\\0'-terminated. "
125                                       "adding '\\0'.\n"));
126                                 valstr = TALLOC_REALLOC_ARRAY(mem_ctx, valstr,
127                                                               char, len + 1);
128                                 if (valstr == NULL) {
129                                         DEBUG(1, ("out of memory\n"));
130                                         TALLOC_FREE(mem_ctx);
131                                         return False;
132                                 }
133                                 valstr[len] = '\0';
134                                 len++;
135                         }
136
137                         if (!lp_canonicalize_parameter(valname, &canon_valname,
138                                                        &inverse))
139                         {
140                                 DEBUG(5, ("Error: lp_canonicalize_parameter "
141                                       "failed after lp_parameter_is_valid. "
142                                       "This should not happen!\n"));
143                                 TALLOC_FREE(mem_ctx);
144                                 return False;
145                         }
146                         DEBUG(10, ("old value name: '%s', canonical value "
147                                    "name: '%s'\n", valname, canon_valname));
148                         if (inverse && lp_string_is_valid_boolean(valstr)) {
149                                 lp_invert_boolean(valstr, &canon_valstr);
150                         } else {
151                                 canon_valstr = valstr;
152                         }
153
154                         ZERO_STRUCTP(value);
155
156                         value->type = REG_SZ;
157                         value->v.sz.str = CONST_DISCARD(char *, canon_valstr);
158                         value->v.sz.len = strlen(canon_valstr) + 1;
159
160                         err = registry_push_value(mem_ctx, value, &value_data);
161                         if (!W_ERROR_IS_OK(err)) {
162                                 DEBUG(10, ("error calling registry_push_value."
163                                       "\n"));
164                                 TALLOC_FREE(mem_ctx);
165                                 return False;
166                         }
167
168                         DEBUG(10, ("adding canonicalized parameter to "
169                                    "container.\n"));
170                         res = regval_ctr_addvalue(new_val_ctr, canon_valname,
171                                                   value->type,
172                                                   (char *)value_data.data,
173                                                   value_data.length);
174                         if (res == 0) {
175                                 DEBUG(10, ("error calling regval_ctr_addvalue. "
176                                       "(no memory?)\n"));
177                                 TALLOC_FREE(mem_ctx);
178                                 return False;
179                         }
180                         DEBUG(10, ("parameter added. container now has %d "
181                                    "values.\n", res));
182
183                         TALLOC_FREE(mem_ctx);
184                 } else {
185                         DEBUG(10, ("%s parameter found, "
186                                    "copying it to new container...\n",
187                                    (lp_parameter_is_valid(valname)?
188                                     "valid":"unknown")));
189                         res = regval_ctr_copyvalue(new_val_ctr, theval);
190                         if (res == 0) {
191                                 DEBUG(10, ("error calling regval_ctr_copyvalue."
192                                            " (no memory?)\n"));
193                                 return False;
194                         }
195                         DEBUG(10, ("parameter copied. container now has %d "
196                                    "values.\n", res));
197                 }
198         }
199         return regdb_ops.store_values(key, new_val_ctr);
200 }
201
202 static BOOL smbconf_reg_access_check(const char *keyname, uint32 requested,
203                                      uint32 *granted,
204                                      const struct nt_user_token *token)
205 {
206         if (!(user_has_privileges(token, &se_disk_operators))) {
207                 return False;
208         }
209
210         *granted = REG_KEY_ALL;
211         return True;
212 }
213
214 static WERROR smbconf_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
215                                   struct security_descriptor **psecdesc)
216 {
217         return regdb_ops.get_secdesc(mem_ctx, key, psecdesc);
218 }
219
220 static WERROR smbconf_set_secdesc(const char *key,
221                                   struct security_descriptor *secdesc)
222 {
223         return regdb_ops.set_secdesc(key, secdesc);
224 }
225
226
227 /*
228  * Table of function pointers for accessing smb.conf data
229  */
230
231 REGISTRY_OPS smbconf_reg_ops = {
232         smbconf_fetch_keys,
233         smbconf_fetch_values,
234         smbconf_store_keys,
235         smbconf_store_values,
236         smbconf_reg_access_check,
237         smbconf_get_secdesc,
238         smbconf_set_secdesc
239 };