r19991: Sorry for this 2000-liner...
[ira/wip.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, const char **pname,
172                      struct registry_value **pval)
173 {
174         struct registry_value *val;
175         WERROR err;
176
177         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
178                 return WERR_ACCESS_DENIED;
179         }
180
181         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
182                 return err;
183         }
184
185         if (idx >= key->values->num_values) {
186                 return WERR_BADFILE;
187         }
188
189         err = registry_pull_value(mem_ctx, &val,
190                                   key->values->values[idx]->type,
191                                   key->values->values[idx]->data_p,
192                                   key->values->values[idx]->size,
193                                   key->values->values[idx]->size);
194         if (!W_ERROR_IS_OK(err)) {
195                 return err;
196         }
197
198         if (pname
199             && !(*pname = talloc_strdup(
200                          mem_ctx, key->values->values[idx]->valuename))) {
201                 SAFE_FREE(val);
202                 return WERR_NOMEM;
203         }
204                 
205         *pval = val;
206         return WERR_OK;
207 }
208
209 WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
210                       const char *name, struct registry_value **pval)
211 {
212         WERROR err;
213         uint32 i;
214
215         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
216                 return WERR_ACCESS_DENIED;
217         }
218
219         if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
220                 return err;
221         }
222
223         for (i=0; i<key->values->num_values; i++) {
224                 if (strequal(key->values->values[i]->valuename, name)) {
225                         return reg_enumvalue(mem_ctx, key, i, NULL, pval);
226                 }
227         }
228
229         return WERR_BADFILE;
230 }
231
232 WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
233                         uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
234                         uint32_t *num_values, uint32_t *max_valnamelen, 
235                         uint32_t *max_valbufsize, uint32_t *secdescsize,
236                         NTTIME *last_changed_time)
237 {
238         uint32 i, max_size;
239         size_t max_len;
240         TALLOC_CTX *mem_ctx;
241         WERROR err;
242         struct security_descriptor *secdesc;
243
244         if (!(key->key->access_granted & SEC_RIGHTS_QUERY_VALUE)) {
245                 return WERR_ACCESS_DENIED;
246         }
247
248         if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
249             !W_ERROR_IS_OK(fill_value_cache(key))) {
250                 return WERR_BADFILE;
251         }
252
253         max_len = 0;
254         for (i=0; i<key->subkeys->num_subkeys; i++) {
255                 max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
256         }
257
258         *num_subkeys = key->subkeys->num_subkeys;
259         *max_subkeylen = max_len;
260         *max_subkeysize = 0;    /* Class length? */
261
262         max_len = 0;
263         max_size = 0;
264         for (i=0; i<key->values->num_values; i++) {
265                 max_len = MAX(max_len,
266                               strlen(key->values->values[i]->valuename));
267                 max_size = MAX(max_size, key->values->values[i]->size);
268         }
269
270         *num_values = key->values->num_values;
271         *max_valnamelen = max_len;
272         *max_valbufsize = max_size;
273
274         if (!(mem_ctx = talloc_new(key))) {
275                 return WERR_NOMEM;
276         }
277
278         err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
279         if (!W_ERROR_IS_OK(err)) {
280                 TALLOC_FREE(mem_ctx);
281                 return err;
282         }
283
284         *secdescsize = sec_desc_size(secdesc);
285         TALLOC_FREE(mem_ctx);
286
287         *last_changed_time = 0;
288
289         return WERR_OK;
290 }
291
292 WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
293                      const char *subkeypath, uint32 desired_access,
294                      struct registry_key **pkey,
295                      enum winreg_CreateAction *paction)
296 {
297         struct registry_key *key = parent;
298         struct registry_key *create_parent;
299         TALLOC_CTX *mem_ctx;
300         char *path, *end;
301         WERROR err;
302         REGSUBKEY_CTR *subkeys;
303
304         if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
305
306         if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
307                 err = WERR_NOMEM;
308                 goto done;
309         }
310
311         while ((end = strchr(path, '\\')) != NULL) {
312                 struct registry_key *tmp;
313                 enum winreg_CreateAction action;
314
315                 *end = '\0';
316
317                 err = reg_createkey(mem_ctx, key, path,
318                                     SEC_RIGHTS_ENUM_SUBKEYS, &tmp, &action);
319                 if (!W_ERROR_IS_OK(err)) {
320                         goto done;
321                 }
322
323                 if (key != parent) {
324                         TALLOC_FREE(key);
325                 }
326
327                 key = tmp;
328                 path = end+1;
329         }
330
331         /*
332          * At this point, "path" contains the one-element subkey of "key". We
333          * can try to open it.
334          */
335
336         err = reg_openkey(ctx, key, path, desired_access, pkey);
337         if (W_ERROR_IS_OK(err)) {
338                 *paction = REG_OPENED_EXISTING_KEY;
339                 return WERR_OK;
340         }
341
342         if (!W_ERROR_EQUAL(err, WERR_BADFILE)) {
343                 /*
344                  * Something but "notfound" has happened, so bail out
345                  */
346                 goto done;
347         }
348
349         /*
350          * We have to make a copy of the current key, as we opened it only
351          * with ENUM_SUBKEY access.
352          */
353
354         err = reg_openkey(mem_ctx, key, "", SEC_RIGHTS_CREATE_SUBKEY,
355                           &create_parent);
356         if (!W_ERROR_IS_OK(err)) {
357                 goto done;
358         }
359
360         /*
361          * Actually create the subkey
362          */
363
364         if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
365                 err = WERR_NOMEM;
366                 goto done;
367         }
368
369         err = fill_subkey_cache(create_parent);
370         if (!W_ERROR_IS_OK(err)) goto done;
371
372         err = regsubkey_ctr_addkey(create_parent->subkeys, path);
373         if (!W_ERROR_IS_OK(err)) goto done;
374
375         if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
376                 TALLOC_FREE(create_parent->subkeys);
377                 err = WERR_REG_IO_FAILURE;
378                 goto done;
379         }
380
381         /*
382          * Now open the newly created key
383          */
384
385         err = reg_openkey(ctx, create_parent, path, desired_access, pkey);
386         if (W_ERROR_IS_OK(err) && (paction != NULL)) {
387                 *paction = REG_CREATED_NEW_KEY;
388         }
389
390  done:
391         TALLOC_FREE(mem_ctx);
392         return err;
393 }
394                      
395
396 WERROR reg_deletekey(struct registry_key *parent, const char *path)
397 {
398         WERROR err;
399         TALLOC_CTX *mem_ctx;
400         char *name, *end;
401         int num_subkeys;
402
403         if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
404
405         if (!(name = talloc_strdup(mem_ctx, path))) {
406                 err = WERR_NOMEM;
407                 goto error;
408         }
409
410         if ((end = strrchr(name, '\\')) != NULL) {
411                 struct registry_key *tmp;
412
413                 *end = '\0';
414
415                 err = reg_openkey(mem_ctx, parent, name,
416                                   SEC_RIGHTS_CREATE_SUBKEY, &tmp);
417                 if (!W_ERROR_IS_OK(err)) {
418                         goto error;
419                 }
420
421                 parent = tmp;
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