r23578: When calling DeleteKey for a key that has subkey(s), Windows
[kai/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         SMB_ASSERT(hive != NULL);
66         SMB_ASSERT(hive[0] != '\0');
67         SMB_ASSERT(strchr(hive, '\\') == NULL);
68
69         return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access,
70                                     pkey);
71 }
72
73 WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
74                    const char *name, uint32 desired_access,
75                    struct registry_key **pkey)
76 {
77         struct registry_key *direct_parent = parent;
78         WERROR err;
79         char *p, *path, *to_free;
80         size_t len;
81
82         if (!(path = SMB_STRDUP(name))) {
83                 return WERR_NOMEM;
84         }
85         to_free = path;
86
87         len = strlen(path);
88
89         if ((len > 0) && (path[len-1] == '\\')) {
90                 path[len-1] = '\0';
91         }
92
93         while ((p = strchr(path, '\\')) != NULL) {
94                 char *name_component;
95                 struct registry_key *tmp;
96
97                 if (!(name_component = SMB_STRNDUP(path, (p - path)))) {
98                         err = WERR_NOMEM;
99                         goto error;
100                 }
101
102                 err = regkey_open_onelevel(mem_ctx, direct_parent,
103                                            name_component, parent->token,
104                                            SEC_RIGHTS_ENUM_SUBKEYS, &tmp);
105                 SAFE_FREE(name_component);
106
107                 if (!W_ERROR_IS_OK(err)) {
108                         goto error;
109                 }
110                 if (direct_parent != parent) {
111                         TALLOC_FREE(direct_parent);
112                 }
113
114                 direct_parent = tmp;
115                 path = p+1;
116         }
117
118         err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
119                                    desired_access, pkey);
120  error:
121         if (direct_parent != parent) {
122                 TALLOC_FREE(direct_parent);
123         }
124         SAFE_FREE(to_free);
125         return err;
126 }
127
128 WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
129                    uint32 idx, char **name, NTTIME *last_write_time)
130 {
131         WERROR err;
132
133         if (!(key->key->access_granted & SEC_RIGHTS_ENUM_SUBKEYS)) {
134                 return WERR_ACCESS_DENIED;
135         }
136
137         if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
138                 return err;
139         }
140
141         if (idx >= key->subkeys->num_subkeys) {
142                 return WERR_NO_MORE_ITEMS;
143         }
144
145         if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
146                 return WERR_NOMEM;
147         }
148
149         if (last_write_time) {
150                 *last_write_time = 0;
151         }
152
153         return WERR_OK;
154 }
155
156 WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
157                      uint32 idx, char **pname, struct registry_value **pval)
158 {
159         struct registry_value *val;
160         WERROR err;
161
162         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
163                 return WERR_ACCESS_DENIED;
164         }
165
166         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
167                 return err;
168         }
169
170         if (idx >= key->values->num_values) {
171                 return WERR_NO_MORE_ITEMS;
172         }
173
174         err = registry_pull_value(mem_ctx, &val,
175                                   key->values->values[idx]->type,
176                                   key->values->values[idx]->data_p,
177                                   key->values->values[idx]->size,
178                                   key->values->values[idx]->size);
179         if (!W_ERROR_IS_OK(err)) {
180                 return err;
181         }
182
183         if (pname
184             && !(*pname = talloc_strdup(
185                          mem_ctx, key->values->values[idx]->valuename))) {
186                 SAFE_FREE(val);
187                 return WERR_NOMEM;
188         }
189                 
190         *pval = val;
191         return WERR_OK;
192 }
193
194 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
195                       const char *name, struct registry_value **pval)
196 {
197         WERROR err;
198         uint32 i;
199
200         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
201                 return WERR_ACCESS_DENIED;
202         }
203
204         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
205                 return err;
206         }
207
208         for (i=0; i<key->values->num_values; i++) {
209                 if (strequal(key->values->values[i]->valuename, name)) {
210                         return reg_enumvalue(mem_ctx, key, i, NULL, pval);
211                 }
212         }
213
214         return WERR_BADFILE;
215 }
216
217 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
218                         uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
219                         uint32_t *num_values, uint32_t *max_valnamelen, 
220                         uint32_t *max_valbufsize, uint32_t *secdescsize,
221                         NTTIME *last_changed_time)
222 {
223         uint32 i, max_size;
224         size_t max_len;
225         TALLOC_CTX *mem_ctx;
226         WERROR err;
227         struct security_descriptor *secdesc;
228
229         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
230                 return WERR_ACCESS_DENIED;
231         }
232
233         if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
234             !W_ERROR_IS_OK(fill_value_cache(key))) {
235                 return WERR_BADFILE;
236         }
237
238         max_len = 0;
239         for (i=0; i<key->subkeys->num_subkeys; i++) {
240                 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
241         }
242
243         *num_subkeys = key->subkeys->num_subkeys;
244         *max_subkeylen = max_len;
245         *max_subkeysize = 0;    /* Class length? */
246
247         max_len = 0;
248         max_size = 0;
249         for (i=0; i<key->values->num_values; i++) {
250                 max_len = MAX(max_len,
251                               strlen(key->values->values[i]->valuename));
252                 max_size = MAX(max_size, key->values->values[i]->size);
253         }
254
255         *num_values = key->values->num_values;
256         *max_valnamelen = max_len;
257         *max_valbufsize = max_size;
258
259         if (!(mem_ctx = talloc_new(key))) {
260                 return WERR_NOMEM;
261         }
262
263         err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
264         if (!W_ERROR_IS_OK(err)) {
265                 TALLOC_FREE(mem_ctx);
266                 return err;
267         }
268
269         *secdescsize = sec_desc_size(secdesc);
270         TALLOC_FREE(mem_ctx);
271
272         *last_changed_time = 0;
273
274         return WERR_OK;
275 }
276
277 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
278                      const char *subkeypath, uint32 desired_access,
279                      struct registry_key **pkey,
280                      enum winreg_CreateAction *paction)
281 {
282         struct registry_key *key = parent;
283         struct registry_key *create_parent;
284         TALLOC_CTX *mem_ctx;
285         char *path, *end;
286         WERROR err;
287         REGSUBKEY_CTR *subkeys;
288
289         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
290
291         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
292                 err = WERR_NOMEM;
293                 goto done;
294         }
295
296         while ((end = strchr(path, '\\')) != NULL) {
297                 struct registry_key *tmp;
298                 enum winreg_CreateAction action;
299
300                 *end = '\0';
301
302                 err = reg_createkey(mem_ctx, key, path,
303                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
304                 if (!W_ERROR_IS_OK(err)) {
305                         goto done;
306                 }
307
308                 if (key != parent) {
309                         TALLOC_FREE(key);
310                 }
311
312                 key = tmp;
313                 path = end+1;
314         }
315
316         /*
317          * At this point, "path" contains the one-element subkey of "key". We
318          * can try to open it.
319          */
320
321         err = reg_openkey(ctx, key, path, desired_access, pkey);
322         if (W_ERROR_IS_OK(err)) {
323                 if (paction != NULL) {
324                         *paction = REG_OPENED_EXISTING_KEY;
325                 }
326                 goto done;
327         }
328
329         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
330                 /*
331                  * Something but "notfound" has happened, so bail out
332                  */
333                 goto done;
334         }
335
336         /*
337          * We have to make a copy of the current key, as we opened it only
338          * with ENUM_SUBKEY access.
339          */
340
341         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
342                           &create_parent);
343         if (!W_ERROR_IS_OK(err)) {
344                 goto done;
345         }
346
347         /*
348          * Actually create the subkey
349          */
350
351         if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
352                 err = WERR_NOMEM;
353                 goto done;
354         }
355
356         err = fill_subkey_cache(create_parent);
357         if (!W_ERROR_IS_OK(err)) goto done;
358
359         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
360         if (!W_ERROR_IS_OK(err)) goto done;
361
362         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
363                 TALLOC_FREE(create_parent->subkeys);
364                 err = WERR_REG_IO_FAILURE;
365                 goto done;
366         }
367
368         /*
369          * Now open the newly created key
370          */
371
372         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
373         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
374                 *paction = REG_CREATED_NEW_KEY;
375         }
376
377  done:
378         TALLOC_FREE(mem_ctx);
379         return err;
380 }
381                      
382
383 WERROR reg_deletekey(struct registry_key *parent, const char *path)
384 {
385         WERROR err;
386         TALLOC_CTX *mem_ctx;
387         char *name, *end;
388         int num_subkeys;
389         struct registry_key *tmp_key;
390
391         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
392
393         if (!(name = talloc_strdup(mem_ctx, path))) {
394                 err = WERR_NOMEM;
395                 goto error;
396         }
397
398         /* check if the key has subkeys */
399         err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &tmp_key);
400         if (!W_ERROR_IS_OK(err)) {
401                 goto error;
402         }
403         if (!W_ERROR_IS_OK(err = fill_subkey_cache(tmp_key))) {
404                 goto error;
405         }
406         if (tmp_key->subkeys->num_subkeys > 0) {
407                 err = WERR_ACCESS_DENIED;
408                 goto error;
409         }
410
411         /* no subkeys - proceed with delete */
412         if ((end = strrchr(name, '\\')) != NULL) {
413                 *end = '\0';
414
415                 err = reg_openkey(mem_ctx, parent, name,
416                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
417                 if (!W_ERROR_IS_OK(err)) {
418                         goto error;
419                 }
420
421                 parent = tmp_key;
422                 name = end+1;
423         }
424
425         if (name[0] == '\0') {
426                 err = WERR_INVALID_PARAM;
427                 goto error;
428         }
429
430         if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
431                 goto error;
432         }
433
434         num_subkeys = parent->subkeys->num_subkeys;
435
436         if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
437                 err = WERR_BADFILE;
438                 goto error;
439         }
440
441         if (!store_reg_keys(parent->key, parent->subkeys)) {
442                 TALLOC_FREE(parent->subkeys);
443                 err = WERR_REG_IO_FAILURE;
444                 goto error;
445         }
446
447         err = WERR_OK;
448  error:
449         TALLOC_FREE(mem_ctx);
450         return err;
451 }
452
453 WERROR reg_setvalue(struct registry_key *key, const char *name,
454                     const struct registry_value *val)
455 {
456         WERROR err;
457         DATA_BLOB value_data;
458         int res;
459
460         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
461                 return WERR_ACCESS_DENIED;
462         }
463
464         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
465                 return err;
466         }
467
468         err = registry_push_value(key, val, &value_data);
469         if (!W_ERROR_IS_OK(err)) {
470                 return err;
471         }
472
473         res = regval_ctr_addvalue(key->values, name, val->type,
474                                   (char *)value_data.data, value_data.length);
475         TALLOC_FREE(value_data.data);
476
477         if (res == 0) {
478                 TALLOC_FREE(key->values);
479                 return WERR_NOMEM;
480         }
481
482         if (!store_reg_values(key->key, key->values)) {
483                 TALLOC_FREE(key->values);
484                 return WERR_REG_IO_FAILURE;
485         }
486
487         return WERR_OK;
488 }
489
490 WERROR reg_deletevalue(struct registry_key *key, const char *name)
491 {
492         WERROR err;
493
494         if (!(key->key->access_granted & SEC_RIGHTS_SET_VALUE)) {
495                 return WERR_ACCESS_DENIED;
496         }
497
498         if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
499                 return err;
500         }
501
502         regval_ctr_delvalue(key->values, name);
503
504         if (!store_reg_values(key->key, key->values)) {
505                 TALLOC_FREE(key->values);
506                 return WERR_REG_IO_FAILURE;
507         }
508
509         return WERR_OK;
510 }
511
512
513 /*
514  * Utility function to open a complete registry path including the hive
515  * prefix. This should become the replacement function for
516  * regkey_open_internal.
517  */
518
519 WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path,
520                      uint32 desired_access, const struct nt_user_token *token,
521                      struct registry_key **pkey)
522 {
523         struct registry_key *hive, *key;
524         char *path, *p;
525         WERROR err;
526
527         if (!(path = SMB_STRDUP(orig_path))) {
528                 return WERR_NOMEM;
529         }
530
531         p = strchr(path, '\\');
532
533         if ((p == NULL) || (p[1] == '\0')) {
534                 /*
535                  * No key behind the hive, just return the hive
536                  */
537
538                 err = reg_openhive(mem_ctx, path, desired_access, token,
539                                    &hive);
540                 if (!W_ERROR_IS_OK(err)) {
541                         SAFE_FREE(path);
542                         return err;
543                 }
544                 SAFE_FREE(path);
545                 *pkey = hive;
546                 return WERR_OK;
547         }
548
549         *p = '\0';
550
551         err = reg_openhive(mem_ctx, path, SEC_RIGHTS_ENUM_SUBKEYS, token,
552                            &hive);
553         if (!W_ERROR_IS_OK(err)) {
554                 SAFE_FREE(path);
555                 return err;
556         }
557
558         err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key);
559
560         TALLOC_FREE(hive);
561         SAFE_FREE(path);
562
563         if (!W_ERROR_IS_OK(err)) {
564                 return err;
565         }
566
567         *pkey = key;
568         return WERR_OK;
569 }
570
571 /* END */