Line data Source code
1 : /* asn1-func.c - Fucntions for the ASN.1 data structures.
2 : * Copyright (C) 2000, 2001 Fabio Fiorina
3 : * Copyright (C) 2001 Free Software Foundation, Inc.
4 : * Copyright (C) 2002, 2003, 2006, 2007, 2010, 2012 g10 Code GmbH
5 : *
6 : * KSBA is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 : * License for more details.
25 : *
26 : * You should have received a copies of the GNU General Public License
27 : * and the GNU Lesser General Public License along with this program;
28 : * if not, see <http://www.gnu.org/licenses/>.
29 : */
30 :
31 : #ifndef BUILD_GENTOOLS
32 : #include <config.h>
33 : #endif
34 :
35 : #include <stdio.h>
36 : #include <stdlib.h>
37 : #include <string.h>
38 : #include <ctype.h>
39 : #include <assert.h>
40 :
41 : #ifdef BUILD_GENTOOLS
42 : # include "gen-help.h"
43 : #else
44 : # include "util.h"
45 : # include "ksba.h"
46 : #endif
47 :
48 : #include "asn1-func.h"
49 :
50 :
51 : static AsnNode resolve_identifier (AsnNode root, AsnNode node, int nestlevel);
52 :
53 :
54 : static AsnNode
55 0 : add_node (node_type_t type)
56 : {
57 : AsnNode punt;
58 :
59 0 : punt = xmalloc (sizeof *punt);
60 :
61 0 : punt->left = NULL;
62 0 : punt->name = NULL;
63 0 : punt->type = type;
64 0 : punt->valuetype = VALTYPE_NULL;
65 0 : punt->value.v_cstr = NULL;
66 0 : punt->off = -1;
67 0 : punt->nhdr = 0;
68 0 : punt->len = 0;
69 0 : punt->down = NULL;
70 0 : punt->right = NULL;
71 0 : punt->link_next = NULL;
72 0 : return punt;
73 : }
74 :
75 : AsnNode
76 0 : _ksba_asn_new_node (node_type_t type)
77 : {
78 0 : return add_node (type);
79 : }
80 :
81 :
82 : int
83 0 : _ksba_asn_is_primitive (node_type_t type)
84 : {
85 0 : switch (type)
86 : {
87 : case TYPE_BOOLEAN:
88 : case TYPE_INTEGER:
89 : case TYPE_BIT_STRING:
90 : case TYPE_OCTET_STRING:
91 : case TYPE_NULL:
92 : case TYPE_OBJECT_ID:
93 : case TYPE_OBJECT_DESCRIPTOR:
94 : case TYPE_REAL:
95 : case TYPE_ENUMERATED:
96 : case TYPE_UTF8_STRING:
97 : case TYPE_REALTIVE_OID:
98 : case TYPE_NUMERIC_STRING:
99 : case TYPE_PRINTABLE_STRING:
100 : case TYPE_TELETEX_STRING:
101 : case TYPE_VIDEOTEX_STRING:
102 : case TYPE_IA5_STRING:
103 : case TYPE_UTC_TIME:
104 : case TYPE_GENERALIZED_TIME:
105 : case TYPE_GRAPHIC_STRING:
106 : case TYPE_VISIBLE_STRING:
107 : case TYPE_GENERAL_STRING:
108 : case TYPE_UNIVERSAL_STRING:
109 : case TYPE_CHARACTER_STRING:
110 : case TYPE_BMP_STRING:
111 : case TYPE_PRE_SEQUENCE:
112 0 : return 1;
113 : default:
114 0 : return 0;
115 : }
116 : }
117 :
118 :
119 : /* Change the value field of the node to the content of buffer value
120 : of size LEN. With VALUE of NULL or LEN of 0 the value field is
121 : deleted */
122 : void
123 0 : _ksba_asn_set_value (AsnNode node,
124 : enum asn_value_type vtype, const void *value, size_t len)
125 : {
126 0 : return_if_fail (node);
127 :
128 0 : if (node->valuetype)
129 : {
130 0 : if (node->valuetype == VALTYPE_CSTR)
131 0 : xfree (node->value.v_cstr);
132 0 : else if (node->valuetype == VALTYPE_MEM)
133 0 : xfree (node->value.v_mem.buf);
134 0 : node->valuetype = 0;
135 : }
136 :
137 0 : switch (vtype)
138 : {
139 : case VALTYPE_NULL:
140 0 : break;
141 : case VALTYPE_BOOL:
142 0 : return_if_fail (len);
143 0 : node->value.v_bool = !!(const unsigned *)value;
144 0 : break;
145 : case VALTYPE_CSTR:
146 0 : node->value.v_cstr = xstrdup (value);
147 0 : break;
148 : case VALTYPE_MEM:
149 0 : node->value.v_mem.len = len;
150 0 : if (len)
151 : {
152 0 : node->value.v_mem.buf = xmalloc (len);
153 0 : memcpy (node->value.v_mem.buf, value, len);
154 : }
155 : else
156 0 : node->value.v_mem.buf = NULL;
157 0 : break;
158 : case VALTYPE_LONG:
159 0 : return_if_fail (sizeof (long) == len);
160 0 : node->value.v_long = *(long *)value;
161 0 : break;
162 :
163 : case VALTYPE_ULONG:
164 0 : return_if_fail (sizeof (unsigned long) == len);
165 0 : node->value.v_ulong = *(unsigned long *)value;
166 0 : break;
167 :
168 : default:
169 0 : return_if_fail (0);
170 : }
171 0 : node->valuetype = vtype;
172 : }
173 :
174 : static void
175 0 : copy_value (AsnNode d, const AsnNode s)
176 : {
177 : char helpbuf[1];
178 0 : const void *buf = NULL;
179 0 : size_t len = 0;
180 :
181 0 : return_if_fail (d != s);
182 :
183 0 : switch (s->valuetype)
184 : {
185 : case VALTYPE_NULL:
186 0 : break;
187 : case VALTYPE_BOOL:
188 0 : len = 1;
189 0 : helpbuf[0] = s->value.v_bool;
190 0 : buf = helpbuf;
191 0 : break;
192 : case VALTYPE_CSTR:
193 0 : buf = s->value.v_cstr;
194 0 : break;
195 : case VALTYPE_MEM:
196 0 : len = s->value.v_mem.len;
197 0 : buf = len? s->value.v_mem.buf : NULL;
198 0 : break;
199 : case VALTYPE_LONG:
200 0 : len = sizeof (long);
201 0 : buf = &s->value.v_long;
202 0 : break;
203 : case VALTYPE_ULONG:
204 0 : len = sizeof (unsigned long);
205 0 : buf = &s->value.v_ulong;
206 0 : break;
207 :
208 : default:
209 0 : return_if_fail (0);
210 : }
211 0 : _ksba_asn_set_value (d, s->valuetype, buf, len);
212 0 : d->off = s->off;
213 0 : d->nhdr = s->nhdr;
214 0 : d->len = s->len;
215 : }
216 :
217 : static AsnNode
218 0 : copy_node (const AsnNode s)
219 : {
220 0 : AsnNode d = add_node (s->type);
221 :
222 0 : if (s->name)
223 0 : d->name = xstrdup (s->name);
224 0 : d->flags = s->flags;
225 0 : copy_value (d, s);
226 0 : return d;
227 : }
228 :
229 :
230 :
231 :
232 : /* Change the name field of the node to NAME.
233 : NAME may be NULL */
234 : void
235 0 : _ksba_asn_set_name (AsnNode node, const char *name)
236 : {
237 0 : return_if_fail (node);
238 :
239 0 : if (node->name)
240 : {
241 0 : xfree (node->name);
242 0 : node->name = NULL;
243 : }
244 :
245 0 : if (name && *name)
246 0 : node->name = xstrdup (name);
247 : }
248 :
249 :
250 : static AsnNode
251 0 : set_right (AsnNode node, AsnNode right)
252 : {
253 0 : if (node == NULL)
254 0 : return node;
255 :
256 0 : node->right = right;
257 0 : if (right)
258 0 : right->left = node;
259 0 : return node;
260 : }
261 :
262 :
263 : static AsnNode
264 0 : set_down (AsnNode node, AsnNode down)
265 : {
266 0 : if (node == NULL)
267 0 : return node;
268 :
269 0 : node->down = down;
270 0 : if (down)
271 0 : down->left = node;
272 0 : return node;
273 : }
274 :
275 :
276 : void
277 0 : _ksba_asn_remove_node (AsnNode node)
278 : {
279 0 : if (node == NULL)
280 0 : return;
281 :
282 0 : xfree (node->name);
283 0 : if (node->valuetype == VALTYPE_CSTR)
284 0 : xfree (node->value.v_cstr);
285 0 : else if (node->valuetype == VALTYPE_MEM)
286 0 : xfree (node->value.v_mem.buf);
287 0 : xfree (node);
288 : }
289 :
290 :
291 : /* find the node with the given name. A name part of "?LAST" matches
292 : the last element of a set of */
293 : static AsnNode
294 0 : find_node (AsnNode root, const char *name, int resolve)
295 : {
296 : AsnNode p;
297 : const char *s;
298 : char buf[129];
299 : int i;
300 :
301 0 : if (!name || !name[0])
302 0 : return NULL;
303 :
304 : /* find the first part */
305 0 : s = name;
306 0 : for (i=0; *s && *s != '.' && i < DIM(buf)-1; s++)
307 0 : buf[i++] = *s;
308 0 : buf[i] = 0;
309 0 : return_null_if_fail (i < DIM(buf)-1);
310 :
311 0 : for (p = root; p && (!p->name || strcmp (p->name, buf)); p = p->right)
312 : ;
313 :
314 : /* find other parts */
315 0 : while (p && *s)
316 : {
317 0 : assert (*s == '.');
318 0 : s++; /* skip the dot */
319 :
320 0 : if (!p->down)
321 0 : return NULL; /* not found */
322 0 : p = p->down;
323 :
324 0 : for (i=0; *s && *s != '.' && i < DIM(buf)-1; s++)
325 0 : buf[i++] = *s;
326 0 : buf[i] = 0;
327 0 : return_null_if_fail (i < DIM(buf)-1);
328 :
329 0 : if (!*buf)
330 : {
331 : /* a double dot can be used to get over an unnamed sequence
332 : in a set - Actually a hack to workaround a bug. We should
333 : rethink the entire node naming issue */
334 : }
335 0 : else if (!strcmp (buf, "?LAST"))
336 : {
337 0 : if (!p)
338 0 : return NULL;
339 0 : while (p->right)
340 0 : p = p->right;
341 : }
342 : else
343 : {
344 0 : for (; p ; p = p->right)
345 : {
346 0 : if (p->name && !strcmp (p->name, buf))
347 0 : break;
348 0 : if (resolve && p->name && p->type == TYPE_IDENTIFIER)
349 : {
350 : AsnNode p2;
351 :
352 0 : p2 = resolve_identifier (root, p, 0);
353 0 : if (p2 && p2->name && !strcmp (p2->name, buf))
354 0 : break;
355 : }
356 : }
357 :
358 0 : if (resolve && p && p->type == TYPE_IDENTIFIER)
359 0 : p = resolve_identifier (root, p, 0);
360 : }
361 : }
362 :
363 0 : return p;
364 : }
365 :
366 : AsnNode
367 0 : _ksba_asn_find_node (AsnNode root, const char *name)
368 : {
369 0 : return find_node (root, name, 0);
370 : }
371 :
372 :
373 : static AsnNode
374 0 : _asn1_find_left (AsnNode node)
375 : {
376 0 : if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
377 0 : return NULL;
378 :
379 0 : return node->left;
380 : }
381 :
382 :
383 : static AsnNode
384 0 : find_up (AsnNode node)
385 : {
386 : AsnNode p;
387 :
388 0 : if (node == NULL)
389 0 : return NULL;
390 :
391 0 : p = node;
392 0 : while ((p->left != NULL) && (p->left->right == p))
393 0 : p = p->left;
394 :
395 0 : return p->left;
396 : }
397 :
398 :
399 :
400 : static void
401 0 : print_value (AsnNode node, FILE *fp)
402 : {
403 0 : if (!node->valuetype)
404 0 : return;
405 0 : fprintf (fp, " vt=%d val=", node->valuetype);
406 0 : switch (node->valuetype)
407 : {
408 : case VALTYPE_BOOL:
409 0 : fputs (node->value.v_bool? "True":"False", fp);
410 0 : break;
411 : case VALTYPE_CSTR:
412 0 : fputs (node->value.v_cstr, fp);
413 0 : break;
414 : case VALTYPE_MEM:
415 : {
416 : size_t n;
417 : unsigned char *p;
418 0 : for (p=node->value.v_mem.buf, n=node->value.v_mem.len; n; n--, p++)
419 0 : fprintf (fp, "%02X", *p);
420 : }
421 0 : break;
422 : case VALTYPE_LONG:
423 0 : fprintf (fp, "%ld", node->value.v_long);
424 0 : break;
425 : case VALTYPE_ULONG:
426 0 : fprintf (fp, "%lu", node->value.v_ulong);
427 0 : break;
428 : default:
429 0 : return_if_fail (0);
430 : }
431 : }
432 :
433 : void
434 0 : _ksba_asn_node_dump (AsnNode p, FILE *fp)
435 : {
436 : const char *typestr;
437 :
438 0 : switch (p->type)
439 : {
440 0 : case TYPE_NULL: typestr = "NULL"; break;
441 0 : case TYPE_CONSTANT: typestr = "CONST"; break;
442 0 : case TYPE_IDENTIFIER: typestr = "IDENTIFIER"; break;
443 0 : case TYPE_INTEGER: typestr = "INTEGER"; break;
444 0 : case TYPE_ENUMERATED: typestr = "ENUMERATED"; break;
445 0 : case TYPE_UTC_TIME: typestr = "UTCTIME"; break;
446 0 : case TYPE_GENERALIZED_TIME: typestr = "GENERALIZEDTIME"; break;
447 0 : case TYPE_BOOLEAN: typestr = "BOOLEAN"; break;
448 0 : case TYPE_SEQUENCE: typestr = "SEQUENCE"; break;
449 0 : case TYPE_PRE_SEQUENCE: typestr = "PRE_SEQUENCE"; break;
450 0 : case TYPE_BIT_STRING: typestr = "BIT_STR"; break;
451 0 : case TYPE_OCTET_STRING: typestr = "OCT_STR"; break;
452 0 : case TYPE_TAG: typestr = "TAG"; break;
453 0 : case TYPE_DEFAULT: typestr = "DEFAULT"; break;
454 0 : case TYPE_SIZE: typestr = "SIZE"; break;
455 0 : case TYPE_SEQUENCE_OF: typestr = "SEQ_OF"; break;
456 0 : case TYPE_OBJECT_ID: typestr = "OBJ_ID"; break;
457 0 : case TYPE_ANY: typestr = "ANY"; break;
458 0 : case TYPE_SET: typestr = "SET"; break;
459 0 : case TYPE_SET_OF: typestr = "SET_OF"; break;
460 0 : case TYPE_CHOICE: typestr = "CHOICE"; break;
461 0 : case TYPE_DEFINITIONS: typestr = "DEFINITIONS"; break;
462 0 : case TYPE_UTF8_STRING: typestr = "UTF8_STRING"; break;
463 0 : case TYPE_NUMERIC_STRING: typestr = "NUMERIC_STRING"; break;
464 0 : case TYPE_PRINTABLE_STRING: typestr = "PRINTABLE_STRING"; break;
465 0 : case TYPE_TELETEX_STRING: typestr = "TELETEX_STRING"; break;
466 0 : case TYPE_IA5_STRING: typestr = "IA5_STRING"; break;
467 0 : default: typestr = "ERROR\n"; break;
468 : }
469 :
470 0 : fprintf (fp, "%s", typestr);
471 0 : if (p->name)
472 0 : fprintf (fp, " `%s'", p->name);
473 0 : print_value (p, fp);
474 0 : fputs (" ", fp);
475 0 : switch (p->flags.class)
476 : {
477 0 : case CLASS_UNIVERSAL: fputs ("U", fp); break;
478 0 : case CLASS_PRIVATE: fputs ("P", fp); break;
479 0 : case CLASS_APPLICATION: fputs ("A", fp); break;
480 0 : case CLASS_CONTEXT: fputs ("C", fp); break;
481 : }
482 :
483 0 : if (p->flags.explicit)
484 0 : fputs (",explicit", fp);
485 0 : if (p->flags.implicit)
486 0 : fputs (",implicit", fp);
487 0 : if (p->flags.is_implicit)
488 0 : fputs (",is_implicit", fp);
489 0 : if (p->flags.has_tag)
490 0 : fputs (",tag", fp);
491 0 : if (p->flags.has_default)
492 0 : fputs (",default", fp);
493 0 : if (p->flags.is_true)
494 0 : fputs (",true", fp);
495 0 : if (p->flags.is_false)
496 0 : fputs (",false", fp);
497 0 : if (p->flags.has_list)
498 0 : fputs (",list", fp);
499 0 : if (p->flags.has_min_max)
500 0 : fputs (",min_max", fp);
501 0 : if (p->flags.is_optional)
502 0 : fputs (",optional", fp);
503 0 : if (p->flags.one_param)
504 0 : fputs (",1_param", fp);
505 0 : if (p->flags.has_size)
506 0 : fputs (",size", fp);
507 0 : if (p->flags.has_defined_by)
508 0 : fputs (",def_by", fp);
509 0 : if (p->flags.has_imports)
510 0 : fputs (",imports", fp);
511 0 : if (p->flags.assignment)
512 0 : fputs (",assign",fp);
513 0 : if (p->flags.in_set)
514 0 : fputs (",in_set",fp);
515 0 : if (p->flags.in_choice)
516 0 : fputs (",in_choice",fp);
517 0 : if (p->flags.in_array)
518 0 : fputs (",in_array",fp);
519 0 : if (p->flags.not_used)
520 0 : fputs (",not_used",fp);
521 0 : if (p->flags.skip_this)
522 0 : fputs (",[skip]",fp);
523 0 : if (p->flags.is_any)
524 0 : fputs (",is_any",fp);
525 0 : if (p->off != -1 )
526 0 : fprintf (fp, " %d.%d.%d", p->off, p->nhdr, p->len );
527 :
528 0 : }
529 :
530 : void
531 0 : _ksba_asn_node_dump_all (AsnNode root, FILE *fp)
532 : {
533 0 : AsnNode p = root;
534 0 : int indent = 0;
535 :
536 0 : while (p)
537 : {
538 0 : fprintf (fp, "%*s", indent, "");
539 0 : _ksba_asn_node_dump (p, fp);
540 0 : putc ('\n', fp);
541 :
542 0 : if (p->down)
543 : {
544 0 : p = p->down;
545 0 : indent += 2;
546 : }
547 0 : else if (p == root)
548 : {
549 0 : p = NULL;
550 0 : break;
551 : }
552 0 : else if (p->right)
553 0 : p = p->right;
554 : else
555 : {
556 : while (1)
557 : {
558 0 : p = find_up (p);
559 0 : if (p == root)
560 : {
561 0 : p = NULL;
562 0 : break;
563 : }
564 0 : indent -= 2;
565 0 : if (p->right)
566 : {
567 0 : p = p->right;
568 0 : break;
569 : }
570 : }
571 : }
572 : }
573 0 : }
574 :
575 : /**
576 : * ksba_asn_tree_dump:
577 : * @tree: A Parse Tree
578 : * @name: Name of the element or NULL
579 : * @fp: dump to this stream
580 : *
581 : * If the first character of the name is a '<' the expanded version of
582 : * the tree will be printed.
583 : *
584 : * This function is a debugging aid.
585 : **/
586 : void
587 0 : ksba_asn_tree_dump (ksba_asn_tree_t tree, const char *name, FILE *fp)
588 : {
589 : AsnNode p, root;
590 0 : int k, expand=0, indent = 0;
591 :
592 0 : if (!tree || !tree->parse_tree)
593 0 : return;
594 :
595 0 : if ( name && *name== '<')
596 : {
597 0 : expand = 1;
598 0 : name++;
599 0 : if (!*name)
600 0 : name = NULL;
601 : }
602 :
603 0 : root = name? _ksba_asn_find_node (tree->parse_tree, name) : tree->parse_tree;
604 0 : if (!root)
605 0 : return;
606 :
607 0 : if (expand)
608 0 : root = _ksba_asn_expand_tree (root, NULL);
609 :
610 0 : p = root;
611 0 : while (p)
612 : {
613 0 : for (k = 0; k < indent; k++)
614 0 : fprintf (fp, " ");
615 0 : _ksba_asn_node_dump (p, fp);
616 0 : putc ('\n', fp);
617 :
618 0 : if (p->down)
619 : {
620 0 : p = p->down;
621 0 : indent += 2;
622 : }
623 0 : else if (p == root)
624 : {
625 0 : p = NULL;
626 0 : break;
627 : }
628 0 : else if (p->right)
629 0 : p = p->right;
630 : else
631 : {
632 : while (1)
633 : {
634 0 : p = find_up (p);
635 0 : if (p == root)
636 : {
637 0 : p = NULL;
638 0 : break;
639 : }
640 0 : indent -= 2;
641 0 : if (p->right)
642 : {
643 0 : p = p->right;
644 0 : break;
645 : }
646 : }
647 : }
648 : }
649 :
650 0 : if (expand)
651 0 : _ksba_asn_release_nodes (root);
652 : }
653 :
654 : int
655 0 : _ksba_asn_delete_structure (AsnNode root)
656 : {
657 : AsnNode p, p2, p3;
658 :
659 0 : if (root == NULL)
660 0 : return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
661 :
662 0 : p = root;
663 0 : while (p)
664 : {
665 0 : if (p->down)
666 : {
667 0 : p = p->down;
668 : }
669 : else
670 : { /* no down */
671 0 : p2 = p->right;
672 0 : if (p != root)
673 : {
674 0 : p3 = find_up (p);
675 0 : set_down (p3, p2);
676 0 : _ksba_asn_remove_node (p);
677 0 : p = p3;
678 : }
679 : else
680 : { /* p==root */
681 0 : p3 = _asn1_find_left (p);
682 0 : if (!p3)
683 : {
684 0 : p3 = find_up (p);
685 0 : if (p3)
686 0 : set_down (p3, p2);
687 : else
688 : {
689 0 : if (p->right)
690 0 : p->right->left = NULL;
691 : }
692 : }
693 : else
694 0 : set_right (p3, p2);
695 0 : _ksba_asn_remove_node (p);
696 0 : p = NULL;
697 : }
698 : }
699 : }
700 0 : return 0;
701 : }
702 :
703 :
704 : /* check that all identifiers referenced in the tree are available */
705 : int
706 0 : _ksba_asn_check_identifier (AsnNode node)
707 : {
708 : AsnNode p, p2;
709 : char name2[129];
710 :
711 0 : if (!node)
712 0 : return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
713 :
714 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
715 : {
716 0 : if (p->type == TYPE_IDENTIFIER && p->valuetype == VALTYPE_CSTR)
717 : {
718 0 : if (strlen (node->name)+strlen(p->value.v_cstr)+2 > DIM(name2))
719 0 : return gpg_error (GPG_ERR_BUG); /* well identifier too long */
720 0 : strcpy (name2, node->name);
721 0 : strcat (name2, ".");
722 0 : strcat (name2, p->value.v_cstr);
723 0 : p2 = _ksba_asn_find_node (node, name2);
724 0 : if (!p2)
725 : {
726 0 : fprintf (stderr,"reference to `%s' not found\n", name2);
727 0 : return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
728 : }
729 : /* fprintf (stdout,"found reference for `%s' (", name2); */
730 : /* print_node (p2, stdout); */
731 : /* fputs (")\n", stdout); */
732 : }
733 0 : else if (p->type == TYPE_OBJECT_ID && p->flags.assignment)
734 : { /* an object ID in an assignment */
735 0 : p2 = p->down;
736 0 : if (p2 && (p2->type == TYPE_CONSTANT))
737 : {
738 0 : if (p2->valuetype == VALTYPE_CSTR && !isdigit (p2->value.v_cstr[0]))
739 : { /* the first constand below is a reference */
740 0 : if (strlen (node->name)
741 0 : +strlen(p->value.v_cstr)+2 > DIM(name2))
742 0 : return gpg_error (GPG_ERR_BUG); /* well identifier too long */
743 0 : strcpy (name2, node->name);
744 0 : strcat (name2, ".");
745 0 : strcat (name2, p2->value.v_cstr);
746 0 : p2 = _ksba_asn_find_node (node, name2);
747 0 : if (!p2)
748 : {
749 0 : fprintf (stderr,"object id reference `%s' not found\n",
750 : name2);
751 0 : return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
752 : }
753 0 : else if ( p2->type != TYPE_OBJECT_ID
754 0 : || !p2->flags.assignment )
755 : {
756 0 : fprintf (stderr,"`%s' is not an object id\n", name2);
757 0 : return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
758 : }
759 : /* fprintf (stdout,"found objid reference for `%s' (", name2); */
760 : /* print_node (p2, stdout); */
761 : /* fputs (")\n", stdout); */
762 : }
763 : }
764 : }
765 : }
766 :
767 0 : return 0;
768 : }
769 :
770 :
771 : /* Get the next node until root is reached in which case NULL is
772 : returned */
773 : AsnNode
774 0 : _ksba_asn_walk_tree (AsnNode root, AsnNode node)
775 : {
776 0 : if (!node)
777 : ;
778 0 : else if (node->down)
779 0 : node = node->down;
780 : else
781 : {
782 0 : if (node == root)
783 0 : node = NULL;
784 0 : else if (node->right)
785 0 : node = node->right;
786 : else
787 : {
788 : for (;;)
789 : {
790 0 : node = find_up (node);
791 0 : if (node == root)
792 : {
793 0 : node = NULL;
794 0 : break;
795 : }
796 0 : if (node->right)
797 : {
798 0 : node = node->right;
799 0 : break;
800 : }
801 : }
802 : }
803 : }
804 :
805 0 : return node;
806 : }
807 :
808 : AsnNode
809 0 : _ksba_asn_walk_tree_up_right (AsnNode root, AsnNode node)
810 : {
811 0 : if (node)
812 : {
813 0 : if (node == root)
814 0 : node = NULL;
815 : else
816 : {
817 : for (;;)
818 : {
819 0 : node = find_up (node);
820 0 : if (node == root)
821 : {
822 0 : node = NULL;
823 0 : break;
824 : }
825 0 : if (node->right)
826 : {
827 0 : node = node->right;
828 0 : break;
829 : }
830 : }
831 : }
832 : }
833 :
834 0 : return node;
835 : }
836 :
837 : /* walk over the tree and change the value type of all integer types
838 : from string to long. */
839 : int
840 0 : _ksba_asn_change_integer_value (AsnNode node)
841 : {
842 : AsnNode p;
843 :
844 0 : if (node == NULL)
845 0 : return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
846 :
847 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
848 : {
849 0 : if (p->type == TYPE_INTEGER && p->flags.assignment)
850 : {
851 0 : if (p->valuetype == VALTYPE_CSTR)
852 : {
853 0 : long val = strtol (p->value.v_cstr, NULL, 10);
854 0 : _ksba_asn_set_value (p, VALTYPE_LONG, &val, sizeof(val));
855 : }
856 : }
857 : }
858 :
859 0 : return 0;
860 : }
861 :
862 :
863 :
864 : /* Expand all object ID constants */
865 : int
866 0 : _ksba_asn_expand_object_id (AsnNode node)
867 : {
868 : AsnNode p, p2, p3, p4, p5;
869 : char name_root[129], name2[129*2+1];
870 :
871 : /* Fixme: Make a cleaner implementation */
872 0 : if (!node)
873 0 : return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
874 0 : if (!node->name)
875 0 : return gpg_error (GPG_ERR_INV_VALUE);
876 0 : if (strlen(node->name) >= DIM(name_root)-1)
877 0 : return gpg_error (GPG_ERR_GENERAL);
878 0 : strcpy (name_root, node->name);
879 :
880 : restart:
881 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
882 : {
883 0 : if (p->type == TYPE_OBJECT_ID && p->flags.assignment)
884 : {
885 0 : p2 = p->down;
886 0 : if (p2 && p2->type == TYPE_CONSTANT)
887 : {
888 0 : if (p2->valuetype == VALTYPE_CSTR
889 0 : && !isdigit (p2->value.v_cstr[0]))
890 : {
891 0 : if (strlen(p2->value.v_cstr)+1+strlen(name2) >= DIM(name2)-1)
892 0 : return gpg_error (GPG_ERR_GENERAL);
893 0 : strcpy (name2, name_root);
894 0 : strcat (name2, ".");
895 0 : strcat (name2, p2->value.v_cstr);
896 0 : p3 = _ksba_asn_find_node (node, name2);
897 0 : if (!p3 || p3->type != TYPE_OBJECT_ID ||
898 0 : !p3->flags.assignment)
899 0 : return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
900 0 : set_down (p, p2->right);
901 0 : _ksba_asn_remove_node (p2);
902 0 : p2 = p;
903 0 : p4 = p3->down;
904 0 : while (p4)
905 : {
906 0 : if (p4->type == TYPE_CONSTANT)
907 : {
908 0 : p5 = add_node (TYPE_CONSTANT);
909 0 : _ksba_asn_set_name (p5, p4->name);
910 0 : _ksba_asn_set_value (p5, VALTYPE_CSTR,
911 0 : p4->value.v_cstr, 0);
912 0 : if (p2 == p)
913 : {
914 0 : set_right (p5, p->down);
915 0 : set_down (p, p5);
916 : }
917 : else
918 : {
919 0 : set_right (p5, p2->right);
920 0 : set_right (p2, p5);
921 : }
922 0 : p2 = p5;
923 : }
924 0 : p4 = p4->right;
925 : }
926 0 : goto restart; /* the most simple way to get it right ;-) */
927 : }
928 : }
929 : }
930 : }
931 0 : return 0;
932 : }
933 :
934 : /* Walk the parse tree and set the default tag where appropriate. The
935 : node must be of type DEFINITIONS */
936 : void
937 0 : _ksba_asn_set_default_tag (AsnNode node)
938 : {
939 : AsnNode p;
940 :
941 0 : return_if_fail (node && node->type == TYPE_DEFINITIONS);
942 :
943 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
944 : {
945 0 : if ( p->type == TYPE_TAG
946 0 : && !p->flags.explicit && !p->flags.implicit)
947 : {
948 0 : if (node->flags.explicit)
949 0 : p->flags.explicit = 1;
950 : else
951 0 : p->flags.implicit = 1;
952 : }
953 : }
954 : /* now mark the nodes which are implicit */
955 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
956 : {
957 0 : if ( p->type == TYPE_TAG && p->flags.implicit && p->down)
958 : {
959 0 : if (p->down->type == TYPE_CHOICE)
960 : ; /* a CHOICE is per se implicit */
961 0 : else if (p->down->type != TYPE_TAG)
962 0 : p->down->flags.is_implicit = 1;
963 : }
964 : }
965 : }
966 :
967 : /* Walk the tree and set the is_set and not_used flags for all nodes below
968 : a node of type SET. */
969 : void
970 0 : _ksba_asn_type_set_config (AsnNode node)
971 : {
972 : AsnNode p, p2;
973 :
974 0 : return_if_fail (node && node->type == TYPE_DEFINITIONS);
975 :
976 0 : for (p = node; p; p = _ksba_asn_walk_tree (node, p))
977 : {
978 0 : if (p->type == TYPE_SET)
979 : {
980 0 : for (p2 = p->down; p2; p2 = p2->right)
981 : {
982 0 : if (p2->type != TYPE_TAG)
983 : {
984 0 : p2->flags.in_set = 1;
985 0 : p2->flags.not_used = 1;
986 : }
987 : }
988 : }
989 0 : else if (p->type == TYPE_CHOICE)
990 : {
991 0 : for (p2 = p->down; p2; p2 = p2->right)
992 : {
993 0 : p2->flags.in_choice = 1;
994 : }
995 : }
996 0 : else if (p->type == TYPE_SEQUENCE_OF || p->type == TYPE_SET_OF)
997 : {
998 0 : for (p2 = p->down; p2; p2 = p2->right)
999 0 : p2->flags.in_array = 1;
1000 : }
1001 0 : else if (p->type == TYPE_ANY)
1002 : { /* Help the DER encoder to track ANY tags */
1003 0 : p->flags.is_any = 1;
1004 : }
1005 : }
1006 : }
1007 :
1008 : /* Create a copy the tree at SRC_ROOT. s is a helper which should be
1009 : set to SRC_ROOT by the caller */
1010 : static AsnNode
1011 0 : copy_tree (AsnNode src_root, AsnNode s)
1012 : {
1013 0 : AsnNode first=NULL, dprev=NULL, d, down, tmp;
1014 0 : AsnNode *link_nextp = NULL;
1015 :
1016 0 : for (; s; s=s->right )
1017 : {
1018 0 : down = s->down;
1019 0 : d = copy_node (s);
1020 0 : if (link_nextp)
1021 0 : *link_nextp = d;
1022 0 : link_nextp = &d->link_next;
1023 :
1024 0 : if (!first)
1025 0 : first = d;
1026 : else
1027 : {
1028 0 : dprev->right = d;
1029 0 : d->left = dprev;
1030 : }
1031 0 : dprev = d;
1032 0 : if (down)
1033 : {
1034 0 : tmp = copy_tree (src_root, down);
1035 0 : if (tmp)
1036 : {
1037 0 : if (link_nextp)
1038 0 : *link_nextp = tmp;
1039 0 : link_nextp = &tmp->link_next;
1040 0 : while (*link_nextp)
1041 0 : link_nextp = &(*link_nextp)->link_next;
1042 : }
1043 :
1044 0 : if (d->down && tmp)
1045 0 : { /* Need to merge it with the existing down */
1046 : AsnNode x;
1047 :
1048 0 : for (x=d->down; x->right; x = x->right)
1049 : ;
1050 0 : x->right = tmp;
1051 0 : tmp->left = x;
1052 : }
1053 : else
1054 : {
1055 0 : d->down = tmp;
1056 0 : if (d->down)
1057 0 : d->down->left = d;
1058 : }
1059 : }
1060 : }
1061 0 : return first;
1062 : }
1063 :
1064 :
1065 :
1066 : static AsnNode
1067 0 : resolve_identifier (AsnNode root, AsnNode node, int nestlevel)
1068 : {
1069 : char buf_space[50];
1070 : char *buf;
1071 : AsnNode n;
1072 : size_t bufsize;
1073 :
1074 0 : if (nestlevel > 20)
1075 0 : return NULL;
1076 :
1077 0 : return_null_if_fail (root);
1078 0 : return_null_if_fail (node->valuetype == VALTYPE_CSTR);
1079 :
1080 0 : bufsize = strlen (root->name) + strlen (node->value.v_cstr) + 2;
1081 0 : if (bufsize <= sizeof buf_space)
1082 0 : buf = buf_space;
1083 : else
1084 : {
1085 0 : buf = xtrymalloc (bufsize);
1086 0 : return_null_if_fail (buf);
1087 : }
1088 0 : strcpy (stpcpy (stpcpy (buf, root->name), "."), node->value.v_cstr);
1089 0 : n = _ksba_asn_find_node (root, buf);
1090 :
1091 : /* We do just a simple indirection. */
1092 0 : if (n && n->type == TYPE_IDENTIFIER)
1093 0 : n = resolve_identifier (root, n, nestlevel+1);
1094 :
1095 0 : if (buf != buf_space)
1096 0 : xfree (buf);
1097 :
1098 0 : return n;
1099 : }
1100 :
1101 :
1102 : static AsnNode
1103 0 : do_expand_tree (AsnNode src_root, AsnNode s, int depth)
1104 : {
1105 0 : AsnNode first=NULL, dprev=NULL, d, down, tmp;
1106 0 : AsnNode *link_nextp = NULL;
1107 :
1108 : /* On the very first level we do not follow the right pointer so that
1109 : we can break out a valid subtree. */
1110 0 : for (; s; s=depth?s->right:NULL )
1111 : {
1112 0 : if (s->type == TYPE_SIZE)
1113 0 : continue; /* this node gets in the way all the time. It
1114 : should be an attribute to a node */
1115 :
1116 0 : down = s->down;
1117 0 : if (s->type == TYPE_IDENTIFIER)
1118 : {
1119 : AsnNode s2, *dp;
1120 :
1121 0 : d = resolve_identifier (src_root, s, 0);
1122 0 : if (!d)
1123 : {
1124 0 : fprintf (stderr, "RESOLVING IDENTIFIER FAILED\n");
1125 0 : continue;
1126 : }
1127 0 : down = d->down;
1128 0 : d = copy_node (d);
1129 0 : if (link_nextp)
1130 0 : *link_nextp = d;
1131 0 : link_nextp = &d->link_next;
1132 0 : if (s->flags.is_optional)
1133 0 : d->flags.is_optional = 1;
1134 0 : if (s->flags.in_choice)
1135 0 : d->flags.in_choice = 1;
1136 0 : if (s->flags.in_array)
1137 0 : d->flags.in_array = 1;
1138 0 : if (s->flags.is_implicit)
1139 0 : d->flags.is_implicit = 1;
1140 0 : if (s->flags.is_any)
1141 0 : d->flags.is_any = 1;
1142 : /* we don't want the resolved name - change it back */
1143 0 : _ksba_asn_set_name (d, s->name);
1144 : /* copy the default and tag attributes */
1145 0 : tmp = NULL;
1146 0 : dp = &tmp;
1147 0 : for (s2=s->down; s2; s2=s2->right)
1148 : {
1149 : AsnNode x;
1150 :
1151 0 : x = copy_node (s2);
1152 0 : if (link_nextp)
1153 0 : *link_nextp = x;
1154 0 : link_nextp = &x->link_next;
1155 0 : x->left = *dp? *dp : d;
1156 0 : *dp = x;
1157 0 : dp = &(*dp)->right;
1158 :
1159 0 : if (x->type == TYPE_TAG)
1160 0 : d->flags.has_tag =1;
1161 0 : else if (x->type == TYPE_DEFAULT)
1162 0 : d->flags.has_default =1;
1163 : }
1164 0 : d->down = tmp;
1165 : }
1166 : else
1167 : {
1168 0 : d = copy_node (s);
1169 0 : if (link_nextp)
1170 0 : *link_nextp = d;
1171 0 : link_nextp = &d->link_next;
1172 : }
1173 :
1174 0 : if (!first)
1175 0 : first = d;
1176 : else
1177 : {
1178 0 : dprev->right = d;
1179 0 : d->left = dprev;
1180 : }
1181 0 : dprev = d;
1182 0 : if (down)
1183 : {
1184 0 : if (depth >= 1000)
1185 : {
1186 0 : fprintf (stderr, "ASN.1 TREE TOO TALL!\n");
1187 0 : tmp = NULL;
1188 : }
1189 : else
1190 : {
1191 0 : tmp = do_expand_tree (src_root, down, depth+1);
1192 0 : if (tmp)
1193 : {
1194 0 : if (link_nextp)
1195 0 : *link_nextp = tmp;
1196 0 : link_nextp = &tmp->link_next;
1197 0 : while (*link_nextp)
1198 0 : link_nextp = &(*link_nextp)->link_next;
1199 : }
1200 : }
1201 0 : if (d->down && tmp)
1202 0 : { /* Need to merge it with the existing down */
1203 : AsnNode x;
1204 :
1205 0 : for (x=d->down; x->right; x = x->right)
1206 : ;
1207 0 : x->right = tmp;
1208 0 : tmp->left = x;
1209 : }
1210 : else
1211 : {
1212 0 : d->down = tmp;
1213 0 : if (d->down)
1214 0 : d->down->left = d;
1215 : }
1216 : }
1217 : }
1218 :
1219 0 : return first;
1220 : }
1221 :
1222 :
1223 : /* Expand the syntax tree so that all references are resolved and we
1224 : are able to store values right in the tree (except for set/sequence
1225 : of). This expanded tree is also an requirement for doing the DER
1226 : decoding as the resolving of identifiers leads to a lot of
1227 : problems. We use more memory of course, but this is negligible
1228 : because the entire code will be simpler and faster */
1229 : AsnNode
1230 0 : _ksba_asn_expand_tree (AsnNode parse_tree, const char *name)
1231 : {
1232 : AsnNode root;
1233 :
1234 0 : root = name? find_node (parse_tree, name, 1) : parse_tree;
1235 0 : return do_expand_tree (parse_tree, root, 0);
1236 : }
1237 :
1238 :
1239 : /* Insert a copy of the entire tree at NODE as the sibling of itself
1240 : and return the copy */
1241 : AsnNode
1242 0 : _ksba_asn_insert_copy (AsnNode node)
1243 : {
1244 : AsnNode n;
1245 : AsnNode *link_nextp;
1246 :
1247 0 : n = copy_tree (node, node);
1248 0 : if (!n)
1249 0 : return NULL; /* out of core */
1250 0 : return_null_if_fail (n->right == node->right);
1251 0 : node->right = n;
1252 0 : n->left = node;
1253 :
1254 : /* FIXME: Consider tail pointer for faster insertion. */
1255 0 : link_nextp = &node->link_next;
1256 0 : while (*link_nextp)
1257 0 : link_nextp = &(*link_nextp)->link_next;
1258 0 : *link_nextp = n;
1259 :
1260 0 : return n;
1261 : }
1262 :
1263 :
1264 : /* Locate a type value sequence like
1265 :
1266 : SEQUENCE {
1267 : type OBJECT IDENTIFIER
1268 : value ANY
1269 : }
1270 :
1271 : below root and return the 'value' node. OIDBUF should contain the
1272 : DER encoding of an OID value. idx is the number of OIDs to skip;
1273 : this can be used to enumerate structures with the same OID */
1274 : AsnNode
1275 0 : _ksba_asn_find_type_value (const unsigned char *image, AsnNode root, int idx,
1276 : const void *oidbuf, size_t oidlen)
1277 : {
1278 : AsnNode n, noid;
1279 :
1280 0 : if (!image || !root)
1281 0 : return NULL;
1282 :
1283 0 : for (n = root; n; n = _ksba_asn_walk_tree (root, n) )
1284 : {
1285 0 : if ( n->type == TYPE_SEQUENCE
1286 0 : && n->down && n->down->type == TYPE_OBJECT_ID)
1287 : {
1288 0 : noid = n->down;
1289 0 : if (noid->off != -1 && noid->len == oidlen
1290 0 : && !memcmp (image + noid->off + noid->nhdr, oidbuf, oidlen)
1291 0 : && noid->right)
1292 : {
1293 0 : if ( !idx-- )
1294 0 : return noid->right;
1295 : }
1296 :
1297 : }
1298 : }
1299 0 : return NULL;
1300 : }
|