Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /*
2 *
3 * registry.c
4 *
5 * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $
6 * $Revision: 1.6 $
7 * $Date: 2007/11/21 00:09:12 $
8 *
9 * Datastore for tracking configuration and related info.
10 *
11 *
12 * Copyright (C) 2005, Network Resonance, Inc.
13 * Copyright (C) 2006, Network Resonance, Inc.
14 * All Rights Reserved
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of Network Resonance, Inc. nor the name of any
26 * contributors to this software may be used to endorse or promote
27 * products derived from this software without specific prior written
28 * permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGE.
41 *
42 *
43 */
45 #include <assert.h>
46 #include <string.h>
47 #ifndef _MSC_VER
48 #include <strings.h>
49 #include <sys/param.h>
50 #include <netinet/in.h>
51 #endif
52 #ifdef OPENSSL
53 #include <openssl/ssl.h>
54 #endif
55 #include <ctype.h>
56 #include "registry.h"
57 #include "registry_int.h"
58 #include "registry_vtbl.h"
59 #include "r_assoc.h"
60 #include "nr_common.h"
61 #include "r_log.h"
62 #include "r_errors.h"
63 #include "r_macros.h"
64 #include "c2ru.h"
66 /* vtbl used to switch hit between local and remote invocations */
67 static nr_registry_module *reg_vtbl = 0;
69 /* must be in the order the types are numbered */
70 static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" };
72 int NR_LOG_REGISTRY=0;
74 NR_registry NR_TOP_LEVEL_REGISTRY = "";
76 int
77 NR_reg_init(void *mode)
78 {
79 int r, _status;
80 nr_registry_module *module = (nr_registry_module*)mode;
81 #ifdef SANITY_CHECKS
82 NR_registry registry;
83 #endif
85 if (reg_vtbl) {
86 if (reg_vtbl != module) {
87 r_log(LOG_GENERIC,LOG_ERR,"Can't reinitialize registry in different mode");
88 ABORT(R_INTERNAL);
89 }
91 return(0);
92 }
94 reg_vtbl = module;
96 if ((r=reg_vtbl->vtbl->init(mode)))
97 ABORT(r);
99 #ifdef SANITY_CHECKS
100 if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry)))
101 ABORT(r);
102 assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0);
103 #endif
105 r_log_init();
106 r_log_register("registry",&NR_LOG_REGISTRY);
108 _status=0;
109 abort:
110 r_log(NR_LOG_REGISTRY,
111 (_status ? LOG_ERR : LOG_INFO),
112 (_status ? "Couldn't initialize registry" : "Initialized registry"));
113 return(_status);
114 }
116 int
117 NR_reg_initted(void)
118 {
119 return reg_vtbl!=0;
120 }
122 #define NRREGGET(func, method, type) \
123 int \
124 func(NR_registry name, type *out) \
125 { \
126 return reg_vtbl->vtbl->method(name, out); \
127 }
129 NRREGGET(NR_reg_get_char, get_char, char)
130 NRREGGET(NR_reg_get_uchar, get_uchar, UCHAR)
131 NRREGGET(NR_reg_get_int2, get_int2, INT2)
132 NRREGGET(NR_reg_get_uint2, get_uint2, UINT2)
133 NRREGGET(NR_reg_get_int4, get_int4, INT4)
134 NRREGGET(NR_reg_get_uint4, get_uint4, UINT4)
135 NRREGGET(NR_reg_get_int8, get_int8, INT8)
136 NRREGGET(NR_reg_get_uint8, get_uint8, UINT8)
137 NRREGGET(NR_reg_get_double, get_double, double)
139 int
140 NR_reg_get_registry(NR_registry name, NR_registry out)
141 {
142 return reg_vtbl->vtbl->get_registry(name, out);
143 }
145 int
146 NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
147 {
148 return reg_vtbl->vtbl->get_bytes(name, out, size, length);
149 }
151 int
152 NR_reg_get_string(NR_registry name, char *out, size_t size)
153 {
154 return reg_vtbl->vtbl->get_string(name, out, size);
155 }
157 int
158 NR_reg_get_length(NR_registry name, size_t *length)
159 {
160 return reg_vtbl->vtbl->get_length(name, length);
161 }
163 int
164 NR_reg_get_type(NR_registry name, NR_registry_type type)
165 {
166 return reg_vtbl->vtbl->get_type(name, type);
167 }
169 #define NRREGSET(func, method, type) \
170 int \
171 func(NR_registry name, type data) \
172 { \
173 return reg_vtbl->vtbl->method(name, data); \
174 }
176 NRREGSET(NR_reg_set_char, set_char, char)
177 NRREGSET(NR_reg_set_uchar, set_uchar, UCHAR)
178 NRREGSET(NR_reg_set_int2, set_int2, INT2)
179 NRREGSET(NR_reg_set_uint2, set_uint2, UINT2)
180 NRREGSET(NR_reg_set_int4, set_int4, INT4)
181 NRREGSET(NR_reg_set_uint4, set_uint4, UINT4)
182 NRREGSET(NR_reg_set_int8, set_int8, INT8)
183 NRREGSET(NR_reg_set_uint8, set_uint8, UINT8)
184 NRREGSET(NR_reg_set_double, set_double, double)
185 NRREGSET(NR_reg_set_string, set_string, char*)
187 int
188 NR_reg_set_registry(NR_registry name)
189 {
190 return reg_vtbl->vtbl->set_registry(name);
191 }
193 int
194 NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length)
195 {
196 return reg_vtbl->vtbl->set_bytes(name, data, length);
197 }
200 int
201 NR_reg_del(NR_registry name)
202 {
203 return reg_vtbl->vtbl->del(name);
204 }
206 int
207 NR_reg_fin(NR_registry name)
208 {
209 return reg_vtbl->vtbl->fin(name);
210 }
212 int
213 NR_reg_get_child_count(char *parent, unsigned int *count)
214 {
215 assert(sizeof(count) == sizeof(size_t));
216 return reg_vtbl->vtbl->get_child_count(parent, (size_t*)count);
217 }
219 int
220 NR_reg_get_child_registry(char *parent, unsigned int i, NR_registry child)
221 {
222 int r, _status;
223 size_t count;
224 NR_registry *children=0;
226 if ((r=reg_vtbl->vtbl->get_child_count(parent, &count)))
227 ABORT(r);
229 if (i >= count)
230 ABORT(R_NOT_FOUND);
231 else {
232 count++;
233 children = (NR_registry *)RCALLOC(count * sizeof(NR_registry));
234 if (!children)
235 ABORT(R_NO_MEMORY);
237 if ((r=reg_vtbl->vtbl->get_children(parent, children, count, &count)))
238 ABORT(r);
240 if (i >= count)
241 ABORT(R_NOT_FOUND);
243 strncpy(child, children[i], sizeof(NR_registry));
244 }
246 _status=0;
247 abort:
248 RFREE(children);
249 return(_status);
250 }
252 int
253 NR_reg_get_children(NR_registry parent, NR_registry *children, size_t size, size_t *length)
254 {
255 return reg_vtbl->vtbl->get_children(parent, children, size, length);
256 }
258 int
259 NR_reg_dump()
260 {
261 int r, _status;
263 if ((r=reg_vtbl->vtbl->dump(0)))
264 ABORT(r);
266 _status=0;
267 abort:
268 return(_status);
269 }
271 // convenience methods, call RFREE on the returned data
272 int
273 NR_reg_alloc_data(NR_registry name, Data *data)
274 {
275 int r, _status;
276 size_t length;
277 UCHAR *tmp = 0;
278 size_t sanity_check;
280 if ((r=NR_reg_get_length(name, &length)))
281 ABORT(r);
283 if (!(tmp = (void*)RMALLOC(length)))
284 ABORT(R_NO_MEMORY);
286 if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check)))
287 ABORT(r);
289 assert(length == sanity_check);
291 data->len = length;
292 data->data = tmp;
294 _status=0;
295 abort:
296 if (_status) {
297 if (tmp) RFREE(tmp);
298 }
299 return(_status);
300 }
302 int
303 NR_reg_alloc_string(NR_registry name, char **data)
304 {
305 int r, _status;
306 size_t length;
307 char *tmp = 0;
309 if ((r=NR_reg_get_length(name, &length)))
310 ABORT(r);
312 if (!(tmp = (void*)RMALLOC(length+1)))
313 ABORT(R_NO_MEMORY);
315 if ((r=NR_reg_get_string(name, tmp, length+1)))
316 ABORT(r);
318 assert(length == strlen(tmp));
320 *data = tmp;
322 _status=0;
323 abort:
324 if (_status) {
325 if (tmp) RFREE(tmp);
326 }
327 return(_status);
328 }
331 char *
332 nr_reg_type_name(int type)
333 {
334 if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY))
335 return(NULL);
337 return(typenames[type]);
338 }
340 int
341 nr_reg_compute_type(char *typename, int *type)
342 {
343 int _status;
344 int i;
346 #ifdef SANITY_CHECKS
347 assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char"));
348 assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR"));
349 assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2"));
350 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2"));
351 assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4"));
352 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4"));
353 assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8"));
354 assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8"));
355 assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double"));
356 assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data"));
357 assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string"));
358 assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry"));
359 assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1));
360 #endif
362 for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) {
363 if (!strcasecmp(typenames[i], typename)) {
364 *type = i;
365 return 0;
366 }
367 }
368 ABORT(R_BAD_ARGS);
370 _status=0;
371 abort:
372 return(_status);
373 }
375 /* More convenience functions: the same as their parents but they
376 take a prefix and a suffix */
377 #define NRGET2(func, type, get) \
378 int \
379 func(NR_registry parent, char *child, type *out) \
380 { \
381 int r, _status; \
382 NR_registry registry; \
383 \
384 if ((r = NR_reg_make_registry(parent, child, registry))) \
385 ABORT(r); \
386 \
387 if ((r = get(registry, out))) { \
388 ABORT(r); \
389 } \
390 \
391 _status = 0; \
392 abort: \
393 return (_status); \
394 }
396 NRGET2(NR_reg_get2_char, char, NR_reg_get_char)
397 NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar)
398 NRGET2(NR_reg_get2_int2, INT2, NR_reg_get_int2)
399 NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2)
400 NRGET2(NR_reg_get2_int4, INT4, NR_reg_get_int4)
401 NRGET2(NR_reg_get2_uint4, UINT4, NR_reg_get_uint4)
402 NRGET2(NR_reg_get2_int8, INT8, NR_reg_get_int8)
403 NRGET2(NR_reg_get2_uint8, UINT8, NR_reg_get_uint8)
404 NRGET2(NR_reg_get2_double, double, NR_reg_get_double)
405 NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string)
406 NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data)
408 int
409 NR_reg_get2_bytes(NR_registry parent, char *child, UCHAR *out, size_t size, size_t *length)
410 {
411 int r, _status;
412 NR_registry registry;
414 if ((r=NR_reg_make_registry(parent, child, registry)))
415 ABORT(r);
417 if ((r=NR_reg_get_bytes(registry, out, size, length)))
418 ABORT(r);
420 _status = 0;
421 abort:
422 return (_status);
423 }
425 int
426 NR_reg_get2_string(NR_registry parent, char *child, char *out, size_t size)
427 {
428 int r, _status;
429 NR_registry registry;
431 if ((r=NR_reg_make_registry(parent, child, registry)))
432 ABORT(r);
434 if ((r=NR_reg_get_string(registry, out, size)))
435 ABORT(r);
437 _status = 0;
438 abort:
439 return (_status);
440 }
442 /* More convenience functions: the same as their parents but they
443 take a prefix and a suffix */
444 #define NRSET2(func, type, set) \
445 int \
446 func(NR_registry parent, char *child, type in) \
447 { \
448 int r, _status; \
449 NR_registry registry; \
450 \
451 if ((r = NR_reg_make_registry(parent, child, registry))) \
452 ABORT(r); \
453 \
454 if ((r = set(registry, in))) { \
455 ABORT(r); \
456 } \
457 \
458 _status = 0; \
459 abort: \
460 return (_status); \
461 }
463 NRSET2(NR_reg_set2_char, char, NR_reg_set_char)
464 NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar)
465 NRSET2(NR_reg_set2_int2, INT2, NR_reg_set_int2)
466 NRSET2(NR_reg_set2_uint2, UINT2, NR_reg_set_uint2)
467 NRSET2(NR_reg_set2_int4, INT4, NR_reg_set_int4)
468 NRSET2(NR_reg_set2_uint4, UINT4, NR_reg_set_uint4)
469 NRSET2(NR_reg_set2_int8, INT8, NR_reg_set_int8)
470 NRSET2(NR_reg_set2_uint8, UINT8, NR_reg_set_uint8)
471 NRSET2(NR_reg_set2_double, double, NR_reg_set_double)
472 NRSET2(NR_reg_set2_string, char*, NR_reg_set_string)
474 int
475 NR_reg_set2_bytes(NR_registry prefix, char *name, UCHAR *data, size_t length)
476 {
477 int r, _status;
478 NR_registry registry;
480 if ((r = NR_reg_make_registry(prefix, name, registry)))
481 ABORT(r);
483 if ((r = NR_reg_set_bytes(registry, data, length)))
484 ABORT(r);
486 _status = 0;
487 abort:
488 return (_status);
489 }
492 int
493 NR_reg_make_child_registry(NR_registry parent, NR_registry descendant, unsigned int generation, NR_registry child)
494 {
495 int _status;
496 size_t length;
498 length = strlen(parent);
500 if (strncasecmp(parent, descendant, length))
501 ABORT(R_BAD_ARGS);
503 while (descendant[length] != '\0') {
504 if (descendant[length] == '.') {
505 if (generation == 0)
506 break;
508 --generation;
509 }
511 ++length;
512 if (length >= sizeof(NR_registry))
513 ABORT(R_BAD_ARGS);
514 }
516 strncpy(child, descendant, length);
517 child[length] = '\0';
519 _status=0;
520 abort:
521 return(_status);
522 }
524 int
525 NR_reg_get2_child_count(NR_registry base, NR_registry name, unsigned int *count)
526 {
527 int r, _status;
528 NR_registry registry;
530 if ((r=nr_c2ru_make_registry(base, name, registry)))
531 ABORT(r);
533 if (r=NR_reg_get_child_count(registry,count))
534 ABORT(r);
536 _status=0;
537 abort:
538 return(_status);
539 }
541 int
542 NR_reg_get2_child_registry(NR_registry base, NR_registry name, unsigned int i, NR_registry child)
543 {
544 int r, _status;
545 NR_registry registry;
547 if ((r=nr_c2ru_make_registry(base, name, registry)))
548 ABORT(r);
550 if (r=NR_reg_get_child_registry(registry, i, child))
551 ABORT(r);
553 _status=0;
554 abort:
555 return(_status);
556 }
559 /* requires parent already in legal form */
560 int
561 NR_reg_make_registry(NR_registry parent, char *child, NR_registry out)
562 {
563 int r, _status;
564 int plen;
565 int clen;
566 char *c;
567 int i;
569 if ((r=nr_reg_is_valid(parent)))
570 ABORT(r);
572 if (*child == '.')
573 ABORT(R_BAD_ARGS);
575 plen = strlen(parent);
576 clen = strlen(child);
577 if ((plen + clen + 2) > sizeof(NR_registry))
578 ABORT(R_BAD_ARGS);
580 if (out != parent)
581 strcpy(out, parent);
583 c = &(out[plen]);
585 if (parent[0] != '\0') {
586 *c = '.';
587 ++c;
588 }
590 for (i = 0; i < clen; ++i, ++c) {
591 *c = child[i];
592 if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c))
593 *c = '_';
594 }
595 if (i == 0 || child[i-1] == '.')
596 ABORT(R_BAD_ARGS);
598 *c = '\0';
600 _status = 0;
601 abort:
602 return _status;
603 }