Line data Source code
1 : /*
2 : * Samba Unix/Linux SMB client library
3 : * Adapter to use reg_parse with the registry api
4 : *
5 : * Copyright (C) Gregor Beck 2010
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 "reg_parse.h"
23 : #include "reg_import.h"
24 : #include "registry.h"
25 : #include "registry/reg_objects.h"
26 : #include <assert.h>
27 :
28 : /* Debuglevel for tracing */
29 : static const int TL = 2;
30 :
31 : struct reg_import {
32 : struct reg_parse_callback reg_parse_callback;
33 : struct reg_import_callback call;
34 : void *open_key;
35 : };
36 :
37 : static int reg_parse_callback_key(struct reg_import *cb_private,
38 : const char *key[], size_t n, bool del);
39 :
40 : static int reg_parse_callback_val(struct reg_import *cb_private,
41 : const char *name, uint32_t type,
42 : const uint8_t *data, size_t len);
43 :
44 : static int reg_parse_callback_val_registry_value(struct reg_import *cb_private,
45 : const char *name,
46 : uint32_t type,
47 : const uint8_t *data,
48 : size_t len);
49 :
50 : static int reg_parse_callback_val_regval_blob(struct reg_import *cb_private,
51 : const char *name, uint32_t type,
52 : const uint8_t *data,
53 : size_t len);
54 :
55 : static int reg_parse_callback_val_del(struct reg_import *cb_private,
56 : const char *name);
57 :
58 : static int reg_parse_callback_comment(struct reg_import *cb_private,
59 : const char *txt);
60 :
61 :
62 : /*******************************************************************************/
63 :
64 250 : int reg_parse_callback_key(struct reg_import *p,
65 : const char *key[], size_t n, bool del)
66 : {
67 250 : WERROR werr = WERR_OK;
68 :
69 250 : DEBUG(TL, ("%s: %s\n", __FUNCTION__, key[0]));
70 :
71 250 : if (p->open_key != NULL) {
72 244 : werr = p->call.closekey(p->call.data, p->open_key);
73 244 : p->open_key = NULL;
74 244 : if (!W_ERROR_IS_OK(werr)) {
75 0 : DEBUG(0, ("closekey failed: %s\n", win_errstr(werr)));
76 : }
77 : }
78 :
79 250 : if (del) {
80 0 : werr = p->call.deletekey(p->call.data, NULL, key[0]);
81 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
82 : /* the key didn't exist, treat as success */
83 0 : werr = WERR_OK;
84 : }
85 0 : if (!W_ERROR_IS_OK(werr)) {
86 0 : DEBUG(0, ("deletekey %s failed: %s\n",
87 : key[0], win_errstr(werr)));
88 : }
89 : } else {
90 0 : bool existing;
91 250 : werr = p->call.createkey(p->call.data, NULL, key[0],
92 : &p->open_key, &existing);
93 250 : if (W_ERROR_IS_OK(werr)) {
94 250 : DEBUG(TL, ("createkey %s %s\n",
95 : existing ? "opened" : "created", key[0]));
96 : } else {
97 0 : DEBUG(0, ("createkey %s failed: %s\n",
98 : key[0], win_errstr(werr)));
99 : }
100 : }
101 :
102 250 : return W_ERROR_IS_OK(werr) ? 0 : -1;
103 : }
104 :
105 : #define DEBUG_ADD_HEX(LEV, PTR, LEN) \
106 : do { \
107 : int i; \
108 : const unsigned char* ptr = (const unsigned char*)PTR; \
109 : for (i=0; i<LEN; i++) { \
110 : DEBUGADD(LEV, ("'%c'(%02x)%s", \
111 : isprint(ptr[i]) ? ptr[i] : '.', \
112 : (unsigned)ptr[i], \
113 : ((i+1 < LEN) && (i+1)%8) \
114 : ? ", " : "\n")); \
115 : } \
116 : } while(0)
117 :
118 : /*----------------------------------------------------------------------------*/
119 50 : int reg_parse_callback_val(struct reg_import *p,
120 : const char *name, uint32_t type,
121 : const uint8_t *data, size_t len)
122 : {
123 50 : WERROR werr = WERR_OK;
124 :
125 50 : DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
126 3818 : DEBUG_ADD_HEX(TL, data, len);
127 :
128 50 : werr = p->call.setval.blob(p->call.data, p->open_key, name, type,
129 : data, len);
130 50 : if (!W_ERROR_IS_OK(werr)) {
131 2 : DEBUG(0, ("setval %s failed: %s\n",
132 : name, win_errstr(werr)));
133 : }
134 :
135 50 : return W_ERROR_IS_OK(werr) ? 0 : -1;
136 : }
137 :
138 : /*----------------------------------------------------------------------------*/
139 1086 : int reg_parse_callback_val_registry_value(struct reg_import *p,
140 : const char *name, uint32_t type,
141 : const uint8_t *data, size_t len)
142 : {
143 1086 : WERROR werr = WERR_OK;
144 1086 : struct registry_value val = {
145 : .type = type,
146 1086 : .data = data_blob_talloc(p, data, len),
147 : };
148 :
149 1086 : DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
150 66472 : DEBUG_ADD_HEX(TL, data, len);
151 :
152 1086 : werr = p->call.setval.registry_value(p->call.data, p->open_key,
153 : name, &val);
154 1086 : if (!W_ERROR_IS_OK(werr)) {
155 0 : DEBUG(0, ("setval %s failed: %s\n",
156 : name, win_errstr(werr)));
157 : }
158 :
159 1086 : data_blob_free(&val.data);
160 1086 : return W_ERROR_IS_OK(werr) ? 0 : -1;
161 : }
162 :
163 : /*----------------------------------------------------------------------------*/
164 0 : int reg_parse_callback_val_regval_blob(struct reg_import *p,
165 : const char *name, uint32_t type,
166 : const uint8_t *data, size_t len)
167 : {
168 0 : WERROR werr = WERR_OK;
169 0 : void* mem_ctx = talloc_new(p);
170 0 : struct regval_blob *v = NULL;
171 :
172 0 : DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len));
173 0 : DEBUG_ADD_HEX(TL, data, len);
174 :
175 0 : v = regval_compose(mem_ctx, name, type, data, len);
176 0 : if (v == NULL) {
177 0 : DEBUG(0, ("regval_compose %s failed\n", name));
178 0 : werr = WERR_NOT_ENOUGH_MEMORY;
179 0 : goto done;
180 : }
181 :
182 0 : werr = p->call.setval.regval_blob(p->call.data, p->open_key, v);
183 0 : if (!W_ERROR_IS_OK(werr)) {
184 0 : DEBUG(0, ("setval %s failed: %s\n",
185 : name, win_errstr(werr)));
186 : }
187 :
188 0 : done:
189 0 : talloc_free(mem_ctx);
190 :
191 0 : return W_ERROR_IS_OK(werr) ? 0 : -1;
192 : }
193 :
194 :
195 : /*----------------------------------------------------------------------------*/
196 :
197 0 : int reg_parse_callback_val_del(struct reg_import *p,
198 : const char *name)
199 : {
200 0 : WERROR werr = WERR_OK;
201 :
202 0 : DEBUG(TL, ("%s: %s\n", __FUNCTION__, name));
203 :
204 0 : werr = p->call.deleteval(p->call.data, p->open_key, name);
205 0 : if (!W_ERROR_IS_OK(werr)) {
206 0 : DEBUG(0, ("deleteval %s failed: %s\n",
207 : name, win_errstr(werr)));
208 : }
209 :
210 0 : return W_ERROR_IS_OK(werr) ? 0 : -1;
211 : }
212 :
213 :
214 8 : int reg_parse_callback_comment(struct reg_import *cb_private,
215 : const char *txt)
216 : {
217 8 : DEBUG(TL, ("%s: %s\n", __FUNCTION__, txt));
218 8 : return 0;
219 : }
220 :
221 : /******************************************************************************/
222 0 : static WERROR nop_callback_open(void* private_data,
223 : void* parent,
224 : const char* name,
225 : void** key)
226 : {
227 0 : return WERR_OK;
228 : }
229 :
230 0 : static WERROR nop_callback_close(void* private_data, void* key)
231 : {
232 0 : return WERR_OK;
233 : }
234 :
235 0 : static WERROR nop_callback_create(void* private_data,
236 : void* parent,
237 : const char* name,
238 : void** key,
239 : bool* existing)
240 : {
241 0 : return WERR_OK;
242 : }
243 :
244 :
245 0 : static WERROR nop_callback_del(void* private_data,
246 : void* parent,
247 : const char* name)
248 : {
249 0 : return WERR_OK;
250 : }
251 :
252 10 : struct reg_parse_callback *reg_import_adapter(TALLOC_CTX *talloc_ctx,
253 : struct reg_import_callback cb)
254 : {
255 0 : struct reg_parse_callback *ret;
256 10 : struct reg_import *p = talloc_zero(talloc_ctx, struct reg_import);
257 10 : if (p == NULL) {
258 0 : goto fail;
259 : }
260 10 : if (cb.openkey == NULL) {
261 10 : cb.openkey = (reg_import_callback_openkey_t)&nop_callback_open;
262 : }
263 10 : if (cb.closekey == NULL) {
264 0 : cb.closekey =
265 : (reg_import_callback_closekey_t)&nop_callback_close;
266 : }
267 10 : if (cb.createkey == NULL) {
268 0 : cb.createkey =
269 : (reg_import_callback_createkey_t)&nop_callback_create;
270 : }
271 10 : if (cb.deletekey == NULL) {
272 0 : cb.deletekey =
273 : (reg_import_callback_deletekey_t)&nop_callback_del;
274 :
275 : }
276 10 : if (cb.deleteval == NULL) {
277 0 : cb.deleteval =
278 : (reg_import_callback_deleteval_t)&nop_callback_del;
279 : }
280 :
281 10 : p->call = cb;
282 :
283 10 : ret = &p->reg_parse_callback;
284 10 : ret->key = (reg_parse_callback_key_t) ®_parse_callback_key;
285 10 : ret->val_del = (reg_parse_callback_val_del_t) ®_parse_callback_val_del;
286 10 : ret->comment = (reg_parse_callback_comment_t) ®_parse_callback_comment;
287 10 : ret->data = p;
288 :
289 10 : switch (cb.setval_type) {
290 8 : case BLOB:
291 8 : assert(cb.setval.blob != NULL);
292 8 : ret->val = (reg_parse_callback_val_t) ®_parse_callback_val;
293 8 : break;
294 2 : case REGISTRY_VALUE:
295 2 : assert(cb.setval.registry_value != NULL);
296 2 : ret->val = (reg_parse_callback_val_t) ®_parse_callback_val_registry_value;
297 2 : break;
298 0 : case REGVAL_BLOB:
299 0 : assert(cb.setval.regval_blob != NULL);
300 0 : ret->val = (reg_parse_callback_val_t) ®_parse_callback_val_regval_blob;
301 0 : break;
302 0 : case NONE:
303 0 : ret->val = NULL;
304 0 : break;
305 0 : default:
306 0 : assert(false);
307 : }
308 :
309 10 : assert((struct reg_parse_callback *)p == ret);
310 10 : return ret;
311 0 : fail:
312 0 : talloc_free(p);
313 0 : return NULL;
314 : }
|