r20004: Remove a const, "name" is allocated anyway
[gd/samba/.git] / source3 / registry / reg_api.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Volker Lendecke 2006
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /* Attempt to wrap the existing API in a more winreg.idl-like way */
22
23 #include "includes.h"
24
25 static WERROR fill_value_cache(struct registry_key *key)
26 {
27         if (key->values != NULL) {
28                 return WERR_OK;
29         }
30
31         if (!(key->values = TALLOC_ZERO_P(key, REGVAL_CTR))) {
32                 return WERR_NOMEM;
33         }
34         if (fetch_reg_values(key->key, key->values) == -1) {
35                 TALLOC_FREE(key->values);
36                 return WERR_BADFILE;
37         }
38
39         return WERR_OK;
40 }
41
42 static WERROR fill_subkey_cache(struct registry_key *key)
43 {
44         if (key->subkeys != NULL) {
45                 return WERR_OK;
46         }
47
48         if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
49                 return WERR_NOMEM;
50         }
51
52         if (fetch_reg_keys(key->key, key->subkeys) == -1) {
53                 TALLOC_FREE(key->subkeys);
54                 return WERR_NO_MORE_ITEMS;
55         }
56
57         return WERR_OK;
58 }
59
60 WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
61                     uint32 desired_access,
62                     const struct nt_user_token *token,
63                     struct registry_key **pkey)
64 {
65         struct registry_key *key;
66         WERROR err;
67
68         SMB_ASSERT(hive[0] != '\0');
69         SMB_ASSERT(strchr(hive, '\\') == NULL);
70
71         if (!(key = TALLOC_ZERO_P(mem_ctx, struct registry_key))) {
72                 return WERR_NOMEM;
73         }
74
75         if (!(key->token = dup_nt_token(key, token))) {
76                 TALLOC_FREE(key);
77                 return WERR_NOMEM;
78         }
79
80         err = regkey_open_internal(key, &key->key, hive, token,
81                                    desired_access);
82
83         if (!W_ERROR_IS_OK(err)) {
84                 TALLOC_FREE(key);
85                 return err;
86         }
87
88         *pkey = key;
89         return WERR_OK;
90
91 }
92
93 WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
94                    const char *name, uint32 desired_access,
95                    struct registry_key **pkey)
96 {
97         struct registry_key *key;
98         WERROR err;
99         char *path;
100
101         if (!(key = TALLOC_ZERO_P(mem_ctx, struct registry_key))) {
102                 return WERR_NOMEM;
103         }
104
105         if (!(key->token = dup_nt_token(key, parent->token))) {
106                 TALLOC_FREE(key);
107                 return WERR_NOMEM;
108         }
109
110         if (name[0] == '\0') {
111                 /*
112                  * Make a copy of the parent
113                  */ 
114                 path = talloc_strdup(key, parent->key->name);
115         }
116         else {
117                 /*
118                  * Normal subpath open
119                  */
120                 path = talloc_asprintf(key, "%s\\%s", parent->key->name,
121                                        name);
122         }
123
124         if (!path) {
125                 TALLOC_FREE(key);
126                 return WERR_NOMEM;
127         }
128
129         err = regkey_open_internal(key, &key->key, path, parent->token,
130                                    desired_access);
131         TALLOC_FREE(path);
132
133         if (!W_ERROR_IS_OK(err)) {
134                 TALLOC_FREE(key);
135                 return err;
136         }
137
138         *pkey = key;
139         return WERR_OK;
140 }
141
142 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
143                    uint32 idx, char **name, NTTIME *last_write_time)
144 {
145         WERROR err;
146
147         if (!(key->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS)) {
148                 return WERR_ACCESS_DENIED;
149         }
150
151         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
152                 return err;
153         }
154
155         if (idx >= key->subkeys->num_subkeys) {
156                 return WERR_NO_MORE_ITEMS;
157         }
158
159         if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
160                 return WERR_NOMEM;
161         }
162
163         if (last_write_time) {
164                 *last_write_time = 0;
165         }
166
167         return WERR_OK;
168 }
169
170 WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
171                      uint32 idx, char **pname, struct registry_value **pval)
172 {
173         struct registry_value *val;
174         WERROR err;
175
176         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
177                 return WERR_ACCESS_DENIED;
178         }
179
180         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
181                 return err;
182         }
183
184         if (idx >= key->values->num_values) {
185                 return WERR_BADFILE;
186         }
187
188         err = registry_pull_value(mem_ctx, &val,
189                                   key->values->values[idx]->type,
190                                   key->values->values[idx]->data_p,
191                                   key->values->values[idx]->size,
192                                   key->values->values[idx]->size);
193         if (!W_ERROR_IS_OK(err)) {
194                 return err;
195         }
196
197         if (pname
198             && !(*pname = talloc_strdup(
199                          mem_ctx, key->values->values[idx]->valuename))) {
200                 SAFE_FREE(val);
201                 return WERR_NOMEM;
202         }
203                 
204         *pval = val;
205         return WERR_OK;
206 }
207
208 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
209                       const char *name, struct registry_value **pval)
210 {
211         WERROR err;
212         uint32 i;
213
214         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
215                 return WERR_ACCESS_DENIED;
216         }
217
218         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
219                 return err;
220         }
221
222         for (i=0; i<key->values->num_values; i++) {
223                 if (strequal(key->values->values[i]->valuename, name)) {
224                         return reg_enumvalue(mem_ctx, key, i, NULL, pval);
225                 }
226         }
227
228         return WERR_BADFILE;
229 }
230
231 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
232                         uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
233                         uint32_t *num_values, uint32_t *max_valnamelen, 
234                         uint32_t *max_valbufsize, uint32_t *secdescsize,
235                         NTTIME *last_changed_time)
236 {
237         uint32 i, max_size;
238         size_t max_len;
239         TALLOC_CTX *mem_ctx;
240         WERROR err;
241         struct security_descriptor *secdesc;
242
243         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
244                 return WERR_ACCESS_DENIED;
245         }
246
247         if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
248             !W_ERROR_IS_OK(fill_value_cache(key))) {
249                 return WERR_BADFILE;
250         }
251
252         max_len = 0;
253         for (i=0; i<key->subkeys->num_subkeys; i++) {
254                 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
255         }
256
257         *num_subkeys = key->subkeys->num_subkeys;
258         *max_subkeylen = max_len;
259         *max_subkeysize = 0;    /* Class length? */
260
261         max_len = 0;
262         max_size = 0;
263         for (i=0; i<key->values->num_values; i++) {
264                 max_len = MAX(max_len,
265                               strlen(key->values->values[i]->valuename));
266                 max_size = MAX(max_size, key->values->values[i]->size);
267         }
268
269         *num_values = key->values->num_values;
270         *max_valnamelen = max_len;
271         *max_valbufsize = max_size;
272
273         if (!(mem_ctx = talloc_new(key))) {
274                 return WERR_NOMEM;
275         }
276
277         err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
278         if (!W_ERROR_IS_OK(err)) {
279                 TALLOC_FREE(mem_ctx);
280                 return err;
281         }
282
283         *secdescsize = sec_desc_size(secdesc);
284         TALLOC_FREE(mem_ctx);
285
286         *last_changed_time = 0;
287
288         return WERR_OK;
289 }
290
291 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
292                      const char *subkeypath, uint32 desired_access,
293                      struct registry_key **pkey,
294                      enum winreg_CreateAction *paction)
295 {
296         struct registry_key *key = parent;
297         struct registry_key *create_parent;
298         TALLOC_CTX *mem_ctx;
299         char *path, *end;
300         WERROR err;
301         REGSUBKEY_CTR *subkeys;
302
303         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
304
305         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
306                 err = WERR_NOMEM;
307                 goto done;
308         }
309
310         while ((end = strchr(path, '\\')) != NULL) {
311                 struct registry_key *tmp;
312                 enum winreg_CreateAction action;
313
314                 *end = '\0';
315
316                 err = reg_createkey(mem_ctx, key, path,
317                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
318                 if (!W_ERROR_IS_OK(err)) {
319                         goto done;
320                 }
321
322                 if (key != parent) {
323                         TALLOC_FREE(key);
324                 }
325
326                 key = tmp;
327                 path = end+1;
328         }
329
330         /*
331          * At this point, "path" contains the one-element subkey of "key". We
332          * can try to open it.
333          */
334
335         err = reg_openkey(ctx, key, path, desired_access, pkey);
336         if (W_ERROR_IS_OK(err)) {
337                 *paction = REG_OPENED_EXISTING_KEY;
338                 return WERR_OK;
339         }
340
341         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
342                 /*
343                  * Something but "notfound" has happened, so bail out
344                  */
345                 goto done;
346         }
347
348         /*
349          * We have to make a copy of the current key, as we opened it only
350          * with ENUM_SUBKEY access.
351          */
352
353         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
354                           &create_parent);
355         if (!W_ERROR_IS_OK(err)) {
356                 goto done;
357         }
358
359         /*
360          * Actually create the subkey
361          */
362
363         if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
364                 err = WERR_NOMEM;
365                 goto done;
366         }
367
368         err = fill_subkey_cache(create_parent);
369         if (!W_ERROR_IS_OK(err)) goto done;
370
371         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
372         if (!W_ERROR_IS_OK(err)) goto done;
373
374         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
375                 TALLOC_FREE(create_parent->subkeys);
376                 err = WERR_REG_IO_FAILURE;
377                 goto done;
378         }
379
380         /*
381          * Now open the newly created key
382          */
383
384         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
385         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
386                 *paction = REG_CREATED_NEW_KEY;
387         }
388
389  done:
390         TALLOC_FREE(mem_ctx);
391         return err;
392 }
393                      
394
395 WERROR reg_deletekey(struct registry_key *parent, const char *path)
396 {
397         WERROR err;
398         TALLOC_CTX *mem_ctx;
399         char *name, *end;
400         int num_subkeys;
401
402         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
403
404         if (!(name = talloc_strdup(mem_ctx, path))) {
405                 err = WERR_NOMEM;
406                 goto error;
407         }
408
409         if ((end = strrchr(name, '\\')) != NULL) {
410                 struct registry_key *tmp;
411
412                 *end = '\0';
413
414                 err = reg_openkey(mem_ctx, parent, name,
415                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp);
416                 if (!W_ERROR_IS_OK(err)) {
417                         goto error;
418                 }
419
420                 parent = tmp;
421                 name = end+1;
422         }
423
424         if (name[0] == '\0') {
425                 err = WERR_INVALID_PARAM;
426                 goto error;
427         }
428
429         if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
430                 goto error;
431         }
432
433         num_subkeys = parent->subkeys->num_subkeys;
434
435         if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
436                 err = WERR_BADFILE;
437                 goto error;
438         }
439
440         if (!store_reg_keys(parent->key, parent->subkeys)) {
441                 TALLOC_FREE(parent->subkeys);
442                 err = WERR_REG_IO_FAILURE;
443                 goto error;
444         }
445
446         err = WERR_OK;
447  error:
448         TALLOC_FREE(mem_ctx);
449         return err;
450 }
451
452 WERROR reg_setvalue(struct registry_key *key, const char *name,
453                     const struct registry_value *val)
454 {
455         WERROR err;
456         DATA_BLOB value_data;
457         int res;
458
459         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
460                 return WERR_ACCESS_DENIED;
461         }
462
463         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
464                 return err;
465         }
466
467         err = registry_push_value(key, val, &value_data);
468         if (!W_ERROR_IS_OK(err)) {
469                 return err;
470         }
471
472         res = regval_ctr_addvalue(key->values, name, val->type,
473                                   (char *)value_data.data, value_data.length);
474         TALLOC_FREE(value_data.data);
475
476         if (res == 0) {
477                 TALLOC_FREE(key->values);
478                 return WERR_NOMEM;
479         }
480
481         if (!store_reg_values(key->key, key->values)) {
482                 TALLOC_FREE(key->values);
483                 return WERR_REG_IO_FAILURE;
484         }
485
486         return WERR_OK;
487 }
488
489 WERROR reg_deletevalue(struct registry_key *key, const char *name)
490 {
491         WERROR err;
492
493         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
494                 return WERR_ACCESS_DENIED;
495         }
496
497         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
498                 return err;
499         }
500
501         regval_ctr_delvalue(key->values, name);
502
503         if (!store_reg_values(key->key, key->values)) {
504                 TALLOC_FREE(key->values);
505                 return WERR_REG_IO_FAILURE;
506         }
507
508         return WERR_OK;
509 }
510