Merge branch 'v4-0-stable' into newmaster
[amitay/samba.git] / source3 / registry / reg_api_regf.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Volker Lendecke 2006
5  *  Copyright (C) Michael Adam 2007-2008
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 #include "registry.h"
23 #include "reg_cachehook.h"
24 #include "regfio.h"
25 #include "reg_util_internal.h"
26 #include "reg_dispatcher.h"
27 #include "reg_objects.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_REGISTRY
31
32 /*******************************************************************
33  Note: topkeypat is the *full* path that this *key will be
34  loaded into (including the name of the key)
35  ********************************************************************/
36
37 static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
38                             REGF_NK_REC *key)
39 {
40         REGF_NK_REC *subkey;
41         struct registry_key_handle registry_key;
42         struct regval_ctr *values;
43         struct regsubkey_ctr *subkeys;
44         int i;
45         char *path = NULL;
46         WERROR result = WERR_OK;
47
48         /* initialize the struct registry_key_handle structure */
49
50         registry_key.ops = reghook_cache_find(topkeypath);
51         if (!registry_key.ops) {
52                 DEBUG(0, ("reg_load_tree: Failed to assign registry_ops "
53                           "to [%s]\n", topkeypath));
54                 return WERR_BADFILE;
55         }
56
57         registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
58         if (!registry_key.name) {
59                 DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
60                 return WERR_NOMEM;
61         }
62
63         /* now start parsing the values and subkeys */
64
65         result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
66         W_ERROR_NOT_OK_RETURN(result);
67
68         result = regval_ctr_init(subkeys, &values);
69         W_ERROR_NOT_OK_RETURN(result);
70
71         /* copy values into the struct regval_ctr */
72
73         for (i=0; i<key->num_values; i++) {
74                 regval_ctr_addvalue(values, key->values[i].valuename,
75                                     key->values[i].type,
76                                     key->values[i].data,
77                                     (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
78         }
79
80         /* copy subkeys into the struct regsubkey_ctr */
81
82         key->subkey_index = 0;
83         while ((subkey = regfio_fetch_subkey( regfile, key ))) {
84                 result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
85                 if (!W_ERROR_IS_OK(result)) {
86                         TALLOC_FREE(subkeys);
87                         return result;
88                 }
89         }
90
91         /* write this key and values out */
92
93         if (!store_reg_values(&registry_key, values)
94             || !store_reg_keys(&registry_key, subkeys))
95         {
96                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
97                 result = WERR_REG_IO_FAILURE;
98         }
99
100         TALLOC_FREE(subkeys);
101
102         if (!W_ERROR_IS_OK(result)) {
103                 return result;
104         }
105
106         /* now continue to load each subkey registry tree */
107
108         key->subkey_index = 0;
109         while ((subkey = regfio_fetch_subkey(regfile, key))) {
110                 path = talloc_asprintf(regfile->mem_ctx,
111                                        "%s\\%s",
112                                        topkeypath,
113                                        subkey->keyname);
114                 if (path == NULL) {
115                         return WERR_NOMEM;
116                 }
117                 result = reg_load_tree(regfile, path, subkey);
118                 if (!W_ERROR_IS_OK(result)) {
119                         break;
120                 }
121         }
122
123         return result;
124 }
125
126 /*******************************************************************
127  ********************************************************************/
128
129 static WERROR restore_registry_key(struct registry_key_handle *krecord,
130                                    const char *fname)
131 {
132         REGF_FILE *regfile;
133         REGF_NK_REC *rootkey;
134         WERROR result;
135
136         /* open the registry file....fail if the file already exists */
137
138         regfile = regfio_open(fname, (O_RDONLY), 0);
139         if (regfile == NULL) {
140                 DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n",
141                           fname, strerror(errno)));
142                 return ntstatus_to_werror(map_nt_error_from_unix(errno));
143         }
144
145         /* get the rootkey from the regf file and then load the tree
146            via recursive calls */
147
148         if (!(rootkey = regfio_rootkey(regfile))) {
149                 regfio_close(regfile);
150                 return WERR_REG_FILE_INVALID;
151         }
152
153         result = reg_load_tree(regfile, krecord->name, rootkey);
154
155         /* cleanup */
156
157         regfio_close(regfile);
158
159         return result;
160 }
161
162 WERROR reg_restorekey(struct registry_key *key, const char *fname)
163 {
164         return restore_registry_key(key->key, fname);
165 }
166
167 /********************************************************************
168 ********************************************************************/
169
170 static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
171                              REGF_NK_REC *parent)
172 {
173         REGF_NK_REC *key;
174         struct regval_ctr *values;
175         struct regsubkey_ctr *subkeys;
176         int i, num_subkeys;
177         char *key_tmp = NULL;
178         char *keyname, *parentpath;
179         char *subkeypath = NULL;
180         char *subkeyname;
181         struct registry_key_handle registry_key;
182         WERROR result = WERR_OK;
183         struct security_descriptor *sec_desc = NULL;
184
185         if (!regfile) {
186                 return WERR_GENERAL_FAILURE;
187         }
188
189         if (!keypath) {
190                 return WERR_OBJECT_PATH_INVALID;
191         }
192
193         /* split up the registry key path */
194
195         key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
196         if (!key_tmp) {
197                 return WERR_NOMEM;
198         }
199         if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
200                 return WERR_OBJECT_PATH_INVALID;
201         }
202
203         if (!keyname) {
204                 keyname = parentpath;
205         }
206
207         /* we need a registry_key_handle object here to enumerate subkeys and values */
208
209         ZERO_STRUCT(registry_key);
210
211         registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
212         if (registry_key.name == NULL) {
213                 return WERR_NOMEM;
214         }
215
216         registry_key.ops = reghook_cache_find(registry_key.name);
217         if (registry_key.ops == NULL) {
218                 return WERR_BADFILE;
219         }
220
221         /* lookup the values and subkeys */
222
223         result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
224         W_ERROR_NOT_OK_RETURN(result);
225
226         result = regval_ctr_init(subkeys, &values);
227         W_ERROR_NOT_OK_RETURN(result);
228
229         fetch_reg_keys(&registry_key, subkeys);
230         fetch_reg_values(&registry_key, values);
231
232         result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
233         if (!W_ERROR_IS_OK(result)) {
234                 goto done;
235         }
236
237         /* write out this key */
238
239         key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
240                                parent);
241         if (key == NULL) {
242                 result = WERR_CAN_NOT_COMPLETE;
243                 goto done;
244         }
245
246         /* write each one of the subkeys out */
247
248         num_subkeys = regsubkey_ctr_numkeys(subkeys);
249         for (i=0; i<num_subkeys; i++) {
250                 subkeyname = regsubkey_ctr_specific_key(subkeys, i);
251                 subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
252                                              keypath, subkeyname);
253                 if (subkeypath == NULL) {
254                         result = WERR_NOMEM;
255                         goto done;
256                 }
257                 result = reg_write_tree(regfile, subkeypath, key);
258                 if (!W_ERROR_IS_OK(result))
259                         goto done;
260         }
261
262         DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));
263
264 done:
265         TALLOC_FREE(subkeys);
266         TALLOC_FREE(registry_key.name);
267
268         return result;
269 }
270
271 static WERROR backup_registry_key(struct registry_key_handle *krecord,
272                                   const char *fname)
273 {
274         REGF_FILE *regfile;
275         WERROR result;
276
277         /* open the registry file....fail if the file already exists */
278
279         regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL),
280                               (S_IREAD|S_IWRITE));
281         if (regfile == NULL) {
282                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n",
283                          fname, strerror(errno) ));
284                 return ntstatus_to_werror(map_nt_error_from_unix(errno));
285         }
286
287         /* write the registry tree to the file  */
288
289         result = reg_write_tree(regfile, krecord->name, NULL);
290
291         /* cleanup */
292
293         regfio_close(regfile);
294
295         return result;
296 }
297
298 WERROR reg_savekey(struct registry_key *key, const char *fname)
299 {
300         return backup_registry_key(key->key, fname);
301 }