Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 : : *
4 : : * This file is part of LIBTASN1.
5 : : *
6 : : * The LIBTASN1 library is free software; you can redistribute it
7 : : * and/or modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful, but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, write to the Free Software
18 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 : : * 02110-1301, USA
20 : : */
21 : :
22 : :
23 : : /*****************************************************/
24 : : /* File: structure.c */
25 : : /* Description: Functions to create and delete an */
26 : : /* ASN1 tree. */
27 : : /*****************************************************/
28 : :
29 : :
30 : : #include <int.h>
31 : : #include <structure.h>
32 : : #include "parser_aux.h"
33 : : #include <gstr.h>
34 : :
35 : :
36 : : extern char _asn1_identifierMissing[];
37 : :
38 : :
39 : : /******************************************************/
40 : : /* Function : _asn1_add_node_only */
41 : : /* Description: creates a new NODE_ASN element. */
42 : : /* Parameters: */
43 : : /* type: type of the new element (see TYPE_ */
44 : : /* and CONST_ constants). */
45 : : /* Return: pointer to the new element. */
46 : : /******************************************************/
47 : : ASN1_TYPE
48 : 1680 : _asn1_add_node_only (unsigned int type)
49 : : {
50 : : ASN1_TYPE punt;
51 : :
52 : 1680 : punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
53 [ - + ]: 1680 : if (punt == NULL)
54 : 0 : return NULL;
55 : :
56 : 1680 : punt->type = type;
57 : :
58 : 1680 : return punt;
59 : : }
60 : :
61 : :
62 : : /******************************************************************/
63 : : /* Function : _asn1_find_left */
64 : : /* Description: returns the NODE_ASN element with RIGHT field that*/
65 : : /* points the element NODE. */
66 : : /* Parameters: */
67 : : /* node: NODE_ASN element pointer. */
68 : : /* Return: NULL if not found. */
69 : : /******************************************************************/
70 : : ASN1_TYPE
71 : 203 : _asn1_find_left (ASN1_TYPE node)
72 : : {
73 [ + - ][ + + ]: 203 : if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
[ + + ]
74 : 122 : return NULL;
75 : :
76 : 203 : return node->left;
77 : : }
78 : :
79 : :
80 : : asn1_retCode
81 : 0 : _asn1_create_static_structure (ASN1_TYPE pointer, char *output_file_name,
82 : : char *vector_name)
83 : : {
84 : : FILE *file;
85 : : ASN1_TYPE p;
86 : : unsigned long t;
87 : :
88 : 0 : file = fopen (output_file_name, "w");
89 : :
90 [ # # ]: 0 : if (file == NULL)
91 : 0 : return ASN1_FILE_NOT_FOUND;
92 : :
93 : 0 : fprintf (file, "#if HAVE_CONFIG_H\n");
94 : 0 : fprintf (file, "# include \"config.h\"\n");
95 : 0 : fprintf (file, "#endif\n\n");
96 : :
97 : 0 : fprintf (file, "#include <libtasn1.h>\n\n");
98 : :
99 : 0 : fprintf (file, "const ASN1_ARRAY_TYPE %s[] = {\n", vector_name);
100 : :
101 : 0 : p = pointer;
102 : :
103 [ # # ]: 0 : while (p)
104 : : {
105 : 0 : fprintf (file, " { ");
106 : :
107 [ # # ]: 0 : if (p->name)
108 : 0 : fprintf (file, "\"%s\", ", p->name);
109 : : else
110 : 0 : fprintf (file, "NULL, ");
111 : :
112 : 0 : t = p->type;
113 [ # # ]: 0 : if (p->down)
114 : 0 : t |= CONST_DOWN;
115 [ # # ]: 0 : if (p->right)
116 : 0 : t |= CONST_RIGHT;
117 : :
118 : 0 : fprintf (file, "%lu, ", t);
119 : :
120 [ # # ]: 0 : if (p->value)
121 : 0 : fprintf (file, "\"%s\"},\n", p->value);
122 : : else
123 : 0 : fprintf (file, "NULL },\n");
124 : :
125 [ # # ]: 0 : if (p->down)
126 : : {
127 : 0 : p = p->down;
128 : : }
129 [ # # ]: 0 : else if (p->right)
130 : : {
131 : 0 : p = p->right;
132 : : }
133 : : else
134 : : {
135 : : while (1)
136 : : {
137 : 0 : p = _asn1_find_up (p);
138 [ # # ]: 0 : if (p == pointer)
139 : : {
140 : 0 : p = NULL;
141 : 0 : break;
142 : : }
143 [ # # ]: 0 : if (p->right)
144 : : {
145 : 0 : p = p->right;
146 : 0 : break;
147 : : }
148 : 0 : }
149 : : }
150 : : }
151 : :
152 : 0 : fprintf (file, " { NULL, 0, NULL }\n};\n");
153 : :
154 : 0 : fclose (file);
155 : :
156 : 0 : return ASN1_SUCCESS;
157 : : }
158 : :
159 : :
160 : : /**
161 : : * asn1_array2tree:
162 : : * @array: specify the array that contains ASN.1 declarations
163 : : * @definitions: return the pointer to the structure created by
164 : : * *ARRAY ASN.1 declarations
165 : : * @errorDescription: return the error description.
166 : : *
167 : : * Creates the structures needed to manage the ASN.1 definitions.
168 : : * @array is a vector created by asn1_parser2array().
169 : : *
170 : : * Returns: %ASN1_SUCCESS if structure was created correctly,
171 : : * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not ASN1_TYPE_EMPTY,
172 : : * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier
173 : : * that is not defined (see @errorDescription for more information),
174 : : * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong.
175 : : **/
176 : : asn1_retCode
177 : 0 : asn1_array2tree (const ASN1_ARRAY_TYPE * array, ASN1_TYPE * definitions,
178 : : char *errorDescription)
179 : : {
180 : 0 : ASN1_TYPE p, p_last = NULL;
181 : : unsigned long k;
182 : : int move;
183 : : asn1_retCode result;
184 : :
185 : :
186 [ # # ]: 0 : if (*definitions != ASN1_TYPE_EMPTY)
187 : 0 : return ASN1_ELEMENT_NOT_EMPTY;
188 : :
189 : 0 : move = UP;
190 : :
191 : 0 : k = 0;
192 [ # # ][ # # ]: 0 : while (array[k].value || array[k].type || array[k].name)
[ # # ]
193 : : {
194 : 0 : p = _asn1_add_node (array[k].type & (~CONST_DOWN));
195 [ # # ]: 0 : if (array[k].name)
196 : 0 : _asn1_set_name (p, array[k].name);
197 [ # # ]: 0 : if (array[k].value)
198 : 0 : _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
199 : :
200 [ # # ]: 0 : if (*definitions == NULL)
201 : 0 : *definitions = p;
202 : :
203 [ # # ]: 0 : if (move == DOWN)
204 : 0 : _asn1_set_down (p_last, p);
205 [ # # ]: 0 : else if (move == RIGHT)
206 : 0 : _asn1_set_right (p_last, p);
207 : :
208 : 0 : p_last = p;
209 : :
210 [ # # ]: 0 : if (array[k].type & CONST_DOWN)
211 : 0 : move = DOWN;
212 [ # # ]: 0 : else if (array[k].type & CONST_RIGHT)
213 : 0 : move = RIGHT;
214 : : else
215 : : {
216 : : while (1)
217 : : {
218 [ # # ]: 0 : if (p_last == *definitions)
219 : 0 : break;
220 : :
221 : 0 : p_last = _asn1_find_up (p_last);
222 : :
223 [ # # ]: 0 : if (p_last == NULL)
224 : 0 : break;
225 : :
226 [ # # ]: 0 : if (p_last->type & CONST_RIGHT)
227 : : {
228 : 0 : p_last->type &= ~CONST_RIGHT;
229 : 0 : move = RIGHT;
230 : 0 : break;
231 : : }
232 : 0 : } /* while */
233 : : }
234 : 0 : k++;
235 : : } /* while */
236 : :
237 [ # # ]: 0 : if (p_last == *definitions)
238 : : {
239 : 0 : result = _asn1_check_identifier (*definitions);
240 [ # # ]: 0 : if (result == ASN1_SUCCESS)
241 : : {
242 : 0 : _asn1_change_integer_value (*definitions);
243 : 0 : _asn1_expand_object_id (*definitions);
244 : : }
245 : : }
246 : : else
247 : : {
248 : 0 : result = ASN1_ARRAY_ERROR;
249 : : }
250 : :
251 [ # # ]: 0 : if (errorDescription != NULL)
252 : : {
253 [ # # ]: 0 : if (result == ASN1_IDENTIFIER_NOT_FOUND)
254 : : {
255 : 0 : Estrcpy (errorDescription, ":: identifier '");
256 : 0 : Estrcat (errorDescription, _asn1_identifierMissing);
257 : 0 : Estrcat (errorDescription, "' not found");
258 : : }
259 : : else
260 : 0 : errorDescription[0] = 0;
261 : : }
262 : :
263 [ # # ]: 0 : if (result != ASN1_SUCCESS)
264 : : {
265 : 0 : _asn1_delete_list_and_nodes ();
266 : 0 : *definitions = ASN1_TYPE_EMPTY;
267 : : }
268 : : else
269 : 0 : _asn1_delete_list ();
270 : :
271 : 0 : return result;
272 : : }
273 : :
274 : : /**
275 : : * asn1_delete_structure:
276 : : * @structure: pointer to the structure that you want to delete.
277 : : *
278 : : * Deletes the structure *@structure. At the end, *@structure is set
279 : : * to ASN1_TYPE_EMPTY.
280 : : *
281 : : * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
282 : : * *@structure was ASN1_TYPE_EMPTY.
283 : : **/
284 : : asn1_retCode
285 : 139 : asn1_delete_structure (ASN1_TYPE * structure)
286 : : {
287 : : ASN1_TYPE p, p2, p3;
288 : :
289 [ + + ]: 139 : if (*structure == ASN1_TYPE_EMPTY)
290 : 12 : return ASN1_ELEMENT_NOT_FOUND;
291 : :
292 : 127 : p = *structure;
293 [ + + ]: 7916 : while (p)
294 : : {
295 [ + + ]: 7789 : if (p->down)
296 : : {
297 : 3831 : p = p->down;
298 : : }
299 : : else
300 : : { /* no down */
301 : 3958 : p2 = p->right;
302 [ + + ]: 3958 : if (p != *structure)
303 : : {
304 : 3831 : p3 = _asn1_find_up (p);
305 : 3831 : _asn1_set_down (p3, p2);
306 : 3831 : _asn1_remove_node (p);
307 : 3831 : p = p3;
308 : : }
309 : : else
310 : : { /* p==root */
311 : 127 : p3 = _asn1_find_left (p);
312 [ + + ]: 127 : if (!p3)
313 : : {
314 : 99 : p3 = _asn1_find_up (p);
315 [ + + ]: 99 : if (p3)
316 : 5 : _asn1_set_down (p3, p2);
317 : : else
318 : : {
319 [ - + ]: 94 : if (p->right)
320 : 0 : p->right->left = NULL;
321 : : }
322 : : }
323 : : else
324 : 28 : _asn1_set_right (p3, p2);
325 : 127 : _asn1_remove_node (p);
326 : 127 : p = NULL;
327 : : }
328 : : }
329 : : }
330 : :
331 : 127 : *structure = ASN1_TYPE_EMPTY;
332 : 139 : return ASN1_SUCCESS;
333 : : }
334 : :
335 : :
336 : :
337 : : /**
338 : : * asn1_delete_element:
339 : : * @structure: pointer to the structure that contains the element you
340 : : * want to delete.
341 : : * @element_name: element's name you want to delete.
342 : : *
343 : : * Deletes the element named *@element_name inside *@structure.
344 : : *
345 : : * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
346 : : * the @element_name was not found.
347 : : **/
348 : : asn1_retCode
349 : 7 : asn1_delete_element (ASN1_TYPE structure, const char *element_name)
350 : : {
351 : : ASN1_TYPE p2, p3, source_node;
352 : :
353 : 7 : source_node = asn1_find_node (structure, element_name);
354 : :
355 [ + + ]: 7 : if (source_node == ASN1_TYPE_EMPTY)
356 : 2 : return ASN1_ELEMENT_NOT_FOUND;
357 : :
358 : 5 : p2 = source_node->right;
359 : 5 : p3 = _asn1_find_left (source_node);
360 [ - + ]: 5 : if (!p3)
361 : : {
362 : 0 : p3 = _asn1_find_up (source_node);
363 [ # # ]: 0 : if (p3)
364 : 0 : _asn1_set_down (p3, p2);
365 [ # # ]: 0 : else if (source_node->right)
366 : 0 : source_node->right->left = NULL;
367 : : }
368 : : else
369 : 5 : _asn1_set_right (p3, p2);
370 : :
371 : 7 : return asn1_delete_structure (&source_node);
372 : : }
373 : :
374 : : ASN1_TYPE
375 : 185 : _asn1_copy_structure3 (ASN1_TYPE source_node)
376 : : {
377 : : ASN1_TYPE dest_node, p_s, p_d, p_d_prev;
378 : : int move;
379 : :
380 [ - + ]: 185 : if (source_node == NULL)
381 : 0 : return NULL;
382 : :
383 : 185 : dest_node = _asn1_add_node_only (source_node->type);
384 : :
385 : 185 : p_s = source_node;
386 : 185 : p_d = dest_node;
387 : :
388 : 185 : move = DOWN;
389 : :
390 : : do
391 : : {
392 [ + + ]: 1044 : if (move != UP)
393 : : {
394 [ + + ]: 883 : if (p_s->name)
395 : 612 : _asn1_set_name (p_d, p_s->name);
396 [ + + ]: 883 : if (p_s->value)
397 : 409 : _asn1_set_value (p_d, p_s->value, p_s->value_len);
398 : 883 : move = DOWN;
399 : : }
400 : : else
401 : 161 : move = RIGHT;
402 : :
403 [ + + ]: 1044 : if (move == DOWN)
404 : : {
405 [ + + ]: 883 : if (p_s->down)
406 : : {
407 : 312 : p_s = p_s->down;
408 : 312 : p_d_prev = p_d;
409 : 312 : p_d = _asn1_add_node_only (p_s->type);
410 : 312 : _asn1_set_down (p_d_prev, p_d);
411 : : }
412 : : else
413 : 571 : move = RIGHT;
414 : : }
415 : :
416 [ + + ]: 1044 : if (p_s == source_node)
417 : 34 : break;
418 : :
419 [ + + ]: 1010 : if (move == RIGHT)
420 : : {
421 [ + + ]: 698 : if (p_s->right)
422 : : {
423 : 386 : p_s = p_s->right;
424 : 386 : p_d_prev = p_d;
425 : 386 : p_d = _asn1_add_node_only (p_s->type);
426 : 386 : _asn1_set_right (p_d_prev, p_d);
427 : : }
428 : : else
429 : 312 : move = UP;
430 : : }
431 [ + + ]: 1010 : if (move == UP)
432 : : {
433 : 312 : p_s = _asn1_find_up (p_s);
434 : 312 : p_d = _asn1_find_up (p_d);
435 : : }
436 : : }
437 [ + + ]: 1010 : while (p_s != source_node);
438 : :
439 : 185 : return dest_node;
440 : : }
441 : :
442 : :
443 : : static ASN1_TYPE
444 : 97 : _asn1_copy_structure2 (ASN1_TYPE root, const char *source_name)
445 : : {
446 : : ASN1_TYPE source_node;
447 : :
448 : 97 : source_node = asn1_find_node (root, source_name);
449 : :
450 : 97 : return _asn1_copy_structure3 (source_node);
451 : :
452 : : }
453 : :
454 : :
455 : : static asn1_retCode
456 : 33 : _asn1_type_choice_config (ASN1_TYPE node)
457 : : {
458 : : ASN1_TYPE p, p2, p3, p4;
459 : : int move, tlen;
460 : :
461 [ - + ]: 33 : if (node == NULL)
462 : 0 : return ASN1_ELEMENT_NOT_FOUND;
463 : :
464 : 33 : p = node;
465 : 33 : move = DOWN;
466 : :
467 [ + + ][ + + ]: 469 : while (!((p == node) && (move == UP)))
468 : : {
469 [ + + ]: 436 : if (move != UP)
470 : : {
471 [ + + ][ + + ]: 334 : if ((type_field (p->type) == TYPE_CHOICE) && (p->type & CONST_TAG))
472 : : {
473 : 2 : p2 = p->down;
474 [ + + ]: 6 : while (p2)
475 : : {
476 [ + + ]: 4 : if (type_field (p2->type) != TYPE_TAG)
477 : : {
478 : 2 : p2->type |= CONST_TAG;
479 : 2 : p3 = _asn1_find_left (p2);
480 [ + + ]: 4 : while (p3)
481 : : {
482 [ + - ]: 2 : if (type_field (p3->type) == TYPE_TAG)
483 : : {
484 : 2 : p4 = _asn1_add_node_only (p3->type);
485 : 2 : tlen = _asn1_strlen (p3->value);
486 [ + - ]: 2 : if (tlen > 0)
487 : 2 : _asn1_set_value (p4, p3->value, tlen + 1);
488 : 2 : _asn1_set_right (p4, p2->down);
489 : 2 : _asn1_set_down (p2, p4);
490 : : }
491 : 2 : p3 = _asn1_find_left (p3);
492 : : }
493 : : }
494 : 4 : p2 = p2->right;
495 : : }
496 : 2 : p->type &= ~(CONST_TAG);
497 : 2 : p2 = p->down;
498 [ + + ]: 6 : while (p2)
499 : : {
500 : 4 : p3 = p2->right;
501 [ + + ]: 4 : if (type_field (p2->type) == TYPE_TAG)
502 : 2 : asn1_delete_structure (&p2);
503 : 4 : p2 = p3;
504 : : }
505 : : }
506 : 334 : move = DOWN;
507 : : }
508 : : else
509 : 102 : move = RIGHT;
510 : :
511 [ + + ]: 436 : if (move == DOWN)
512 : : {
513 [ + + ]: 334 : if (p->down)
514 : 133 : p = p->down;
515 : : else
516 : 201 : move = RIGHT;
517 : : }
518 : :
519 [ + + ]: 436 : if (p == node)
520 : : {
521 : 2 : move = UP;
522 : 2 : continue;
523 : : }
524 : :
525 [ + + ]: 434 : if (move == RIGHT)
526 : : {
527 [ + + ]: 301 : if (p->right)
528 : 168 : p = p->right;
529 : : else
530 : 133 : move = UP;
531 : : }
532 [ + + ]: 434 : if (move == UP)
533 : 133 : p = _asn1_find_up (p);
534 : : }
535 : :
536 : 33 : return ASN1_SUCCESS;
537 : : }
538 : :
539 : :
540 : : static asn1_retCode
541 : 33 : _asn1_expand_identifier (ASN1_TYPE * node, ASN1_TYPE root)
542 : : {
543 : : ASN1_TYPE p, p2, p3;
544 : : char name2[ASN1_MAX_NAME_SIZE + 2];
545 : : int move;
546 : :
547 [ - + ]: 33 : if (node == NULL)
548 : 0 : return ASN1_ELEMENT_NOT_FOUND;
549 : :
550 : 33 : p = *node;
551 : 33 : move = DOWN;
552 : :
553 [ + + ][ + + ]: 533 : while (!((p == *node) && (move == UP)))
554 : : {
555 [ + + ]: 500 : if (move != UP)
556 : : {
557 [ + + ]: 398 : if (type_field (p->type) == TYPE_IDENTIFIER)
558 : : {
559 : 64 : _asn1_str_cpy (name2, sizeof (name2), root->name);
560 : 64 : _asn1_str_cat (name2, sizeof (name2), ".");
561 : 64 : _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
562 : 64 : p2 = _asn1_copy_structure2 (root, name2);
563 [ - + ]: 64 : if (p2 == NULL)
564 : : {
565 : 0 : return ASN1_IDENTIFIER_NOT_FOUND;
566 : : }
567 : 64 : _asn1_set_name (p2, p->name);
568 : 64 : p2->right = p->right;
569 : 64 : p2->left = p->left;
570 [ + + ]: 64 : if (p->right)
571 : 38 : p->right->left = p2;
572 : 64 : p3 = p->down;
573 [ + + ]: 64 : if (p3)
574 : : {
575 [ + + ]: 15 : while (p3->right)
576 : 1 : p3 = p3->right;
577 : 14 : _asn1_set_right (p3, p2->down);
578 : 14 : _asn1_set_down (p2, p->down);
579 : : }
580 : :
581 : 64 : p3 = _asn1_find_left (p);
582 [ + + ]: 64 : if (p3)
583 : 44 : _asn1_set_right (p3, p2);
584 : : else
585 : : {
586 : 20 : p3 = _asn1_find_up (p);
587 [ + - ]: 20 : if (p3)
588 : 20 : _asn1_set_down (p3, p2);
589 : : else
590 : : {
591 : 0 : p2->left = NULL;
592 : : }
593 : : }
594 : :
595 [ - + ]: 64 : if (p->type & CONST_SIZE)
596 : 0 : p2->type |= CONST_SIZE;
597 [ + + ]: 64 : if (p->type & CONST_TAG)
598 : 14 : p2->type |= CONST_TAG;
599 [ + + ]: 64 : if (p->type & CONST_OPTION)
600 : 6 : p2->type |= CONST_OPTION;
601 [ + + ]: 64 : if (p->type & CONST_DEFAULT)
602 : 1 : p2->type |= CONST_DEFAULT;
603 [ - + ]: 64 : if (p->type & CONST_SET)
604 : 0 : p2->type |= CONST_SET;
605 [ - + ]: 64 : if (p->type & CONST_NOT_USED)
606 : 0 : p2->type |= CONST_NOT_USED;
607 : :
608 [ - + ]: 64 : if (p == *node)
609 : 0 : *node = p2;
610 : 64 : _asn1_remove_node (p);
611 : 64 : p = p2;
612 : 64 : move = DOWN;
613 : 64 : continue;
614 : : }
615 : 334 : move = DOWN;
616 : : }
617 : : else
618 : 102 : move = RIGHT;
619 : :
620 [ + + ]: 436 : if (move == DOWN)
621 : : {
622 [ + + ]: 334 : if (p->down)
623 : 133 : p = p->down;
624 : : else
625 : 201 : move = RIGHT;
626 : : }
627 : :
628 [ + + ]: 436 : if (p == *node)
629 : : {
630 : 2 : move = UP;
631 : 2 : continue;
632 : : }
633 : :
634 [ + + ]: 434 : if (move == RIGHT)
635 : : {
636 [ + + ]: 301 : if (p->right)
637 : 168 : p = p->right;
638 : : else
639 : 133 : move = UP;
640 : : }
641 [ + + ]: 434 : if (move == UP)
642 : 133 : p = _asn1_find_up (p);
643 : : }
644 : :
645 : 33 : return ASN1_SUCCESS;
646 : : }
647 : :
648 : :
649 : : /**
650 : : * asn1_create_element:
651 : : * @definitions: pointer to the structure returned by "parser_asn1" function
652 : : * @source_name: the name of the type of the new structure (must be
653 : : * inside p_structure).
654 : : * @element: pointer to the structure created.
655 : : *
656 : : * Creates a structure of type @source_name. Example using
657 : : * "pkix.asn":
658 : : *
659 : : * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
660 : : *
661 : : * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
662 : : * @source_name is not known.
663 : : **/
664 : : asn1_retCode
665 : 33 : asn1_create_element (ASN1_TYPE definitions, const char *source_name,
666 : : ASN1_TYPE * element)
667 : : {
668 : : ASN1_TYPE dest_node;
669 : : int res;
670 : :
671 : 33 : dest_node = _asn1_copy_structure2 (definitions, source_name);
672 : :
673 [ - + ]: 33 : if (dest_node == NULL)
674 : 0 : return ASN1_ELEMENT_NOT_FOUND;
675 : :
676 : 33 : _asn1_set_name (dest_node, "");
677 : :
678 : 33 : res = _asn1_expand_identifier (&dest_node, definitions);
679 : 33 : _asn1_type_choice_config (dest_node);
680 : :
681 : 33 : *element = dest_node;
682 : :
683 : 33 : return res;
684 : : }
685 : :
686 : :
687 : : /**
688 : : * asn1_print_structure:
689 : : * @out: pointer to the output file (e.g. stdout).
690 : : * @structure: pointer to the structure that you want to visit.
691 : : * @name: an element of the structure
692 : : * @mode: specify how much of the structure to print, can be
693 : : * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
694 : : * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
695 : : *
696 : : * Prints on the @out file descriptor the structure's tree starting
697 : : * from the @name element inside the structure @structure.
698 : : **/
699 : : void
700 : 26 : asn1_print_structure (FILE * out, ASN1_TYPE structure, const char *name,
701 : : int mode)
702 : : {
703 : : ASN1_TYPE p, root;
704 : 26 : int k, indent = 0, len, len2, len3;
705 : :
706 [ - + ]: 26 : if (out == NULL)
707 : 0 : return;
708 : :
709 : 26 : root = asn1_find_node (structure, name);
710 : :
711 [ - + ]: 26 : if (root == NULL)
712 : 0 : return;
713 : :
714 : 26 : p = root;
715 [ + + ]: 357 : while (p)
716 : : {
717 [ + + ]: 331 : if (mode == ASN1_PRINT_ALL)
718 : : {
719 [ + + ]: 1088 : for (k = 0; k < indent; k++)
720 : 866 : fprintf (out, " ");
721 : 222 : fprintf (out, "name:");
722 [ + + ]: 222 : if (p->name)
723 : 149 : fprintf (out, "%s ", p->name);
724 : : else
725 : 73 : fprintf (out, "NULL ");
726 : : }
727 : : else
728 : : {
729 [ + + ]: 109 : switch (type_field (p->type))
730 : : {
731 : : case TYPE_CONSTANT:
732 : : case TYPE_TAG:
733 : : case TYPE_SIZE:
734 : 17 : break;
735 : : default:
736 [ + + ]: 884 : for (k = 0; k < indent; k++)
737 : 792 : fprintf (out, " ");
738 : 92 : fprintf (out, "name:");
739 [ + + ]: 92 : if (p->name)
740 : 76 : fprintf (out, "%s ", p->name);
741 : : else
742 : 16 : fprintf (out, "NULL ");
743 : : }
744 : : }
745 : :
746 [ + - ]: 331 : if (mode != ASN1_PRINT_NAME)
747 : : {
748 [ + + + + : 331 : switch (type_field (p->type))
- - + + +
+ + + + +
+ + + - +
+ - - ]
749 : : {
750 : : case TYPE_CONSTANT:
751 [ + + ]: 18 : if (mode == ASN1_PRINT_ALL)
752 : 12 : fprintf (out, "type:CONST");
753 : 18 : break;
754 : : case TYPE_TAG:
755 [ + + ]: 33 : if (mode == ASN1_PRINT_ALL)
756 : 31 : fprintf (out, "type:TAG");
757 : 33 : break;
758 : : case TYPE_SIZE:
759 [ + + ]: 12 : if (mode == ASN1_PRINT_ALL)
760 : 3 : fprintf (out, "type:SIZE");
761 : 12 : break;
762 : : case TYPE_DEFAULT:
763 : 12 : fprintf (out, "type:DEFAULT");
764 : 12 : break;
765 : : case TYPE_NULL:
766 : 0 : fprintf (out, "type:NULL");
767 : 0 : break;
768 : : case TYPE_IDENTIFIER:
769 : 0 : fprintf (out, "type:IDENTIFIER");
770 : 0 : break;
771 : : case TYPE_INTEGER:
772 : 38 : fprintf (out, "type:INTEGER");
773 : 38 : break;
774 : : case TYPE_ENUMERATED:
775 : 1 : fprintf (out, "type:ENUMERATED");
776 : 1 : break;
777 : : case TYPE_TIME:
778 : 4 : fprintf (out, "type:TIME");
779 : 4 : break;
780 : : case TYPE_BOOLEAN:
781 : 5 : fprintf (out, "type:BOOLEAN");
782 : 5 : break;
783 : : case TYPE_SEQUENCE:
784 : 63 : fprintf (out, "type:SEQUENCE");
785 : 63 : break;
786 : : case TYPE_BIT_STRING:
787 : 3 : fprintf (out, "type:BIT_STR");
788 : 3 : break;
789 : : case TYPE_OCTET_STRING:
790 : 15 : fprintf (out, "type:OCT_STR");
791 : 15 : break;
792 : : case TYPE_GENERALSTRING:
793 : 2 : fprintf (out, "type:GENERALSTRING");
794 : 2 : break;
795 : : case TYPE_SEQUENCE_OF:
796 : 3 : fprintf (out, "type:SEQ_OF");
797 : 3 : break;
798 : : case TYPE_OBJECT_ID:
799 : 50 : fprintf (out, "type:OBJ_ID");
800 : 50 : break;
801 : : case TYPE_ANY:
802 : 39 : fprintf (out, "type:ANY");
803 : 39 : break;
804 : : case TYPE_SET:
805 : 0 : fprintf (out, "type:SET");
806 : 0 : break;
807 : : case TYPE_SET_OF:
808 : 17 : fprintf (out, "type:SET_OF");
809 : 17 : break;
810 : : case TYPE_CHOICE:
811 : 16 : fprintf (out, "type:CHOICE");
812 : 16 : break;
813 : : case TYPE_DEFINITIONS:
814 : 0 : fprintf (out, "type:DEFINITIONS");
815 : 0 : break;
816 : : default:
817 : 0 : break;
818 : : }
819 : : }
820 : :
821 [ + + ][ + - ]: 331 : if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
822 : : {
823 [ + + + + : 331 : switch (type_field (p->type))
- + + + +
+ + + + +
+ - ]
824 : : {
825 : : case TYPE_CONSTANT:
826 [ + + ]: 18 : if (mode == ASN1_PRINT_ALL)
827 [ + + ]: 12 : if (p->value)
828 : 11 : fprintf (out, " value:%s", p->value);
829 : 18 : break;
830 : : case TYPE_TAG:
831 [ + + ]: 33 : if (mode == ASN1_PRINT_ALL)
832 [ + - ]: 31 : if (p->value)
833 : 31 : fprintf (out, " value:%s", p->value);
834 : 33 : break;
835 : : case TYPE_SIZE:
836 [ + + ]: 12 : if (mode == ASN1_PRINT_ALL)
837 [ + - ]: 3 : if (p->value)
838 : 3 : fprintf (out, " value:%s", p->value);
839 : 12 : break;
840 : : case TYPE_DEFAULT:
841 [ + + ]: 12 : if (p->value)
842 : 8 : fprintf (out, " value:%s", p->value);
843 [ + + ]: 4 : else if (p->type & CONST_TRUE)
844 : 1 : fprintf (out, " value:TRUE");
845 [ + - ]: 3 : else if (p->type & CONST_FALSE)
846 : 3 : fprintf (out, " value:FALSE");
847 : 12 : break;
848 : : case TYPE_IDENTIFIER:
849 [ # # ]: 0 : if (p->value)
850 : 0 : fprintf (out, " value:%s", p->value);
851 : 0 : break;
852 : : case TYPE_INTEGER:
853 [ + + ]: 38 : if (p->value)
854 : : {
855 : 28 : len2 = -1;
856 : 28 : len = asn1_get_length_der (p->value, p->value_len, &len2);
857 : 28 : fprintf (out, " value:0x");
858 [ + - ]: 28 : if (len > 0)
859 [ + + ]: 74 : for (k = 0; k < len; k++)
860 : 46 : fprintf (out, "%02x", (p->value)[k + len2]);
861 : : }
862 : 38 : break;
863 : : case TYPE_ENUMERATED:
864 [ + - ]: 1 : if (p->value)
865 : : {
866 : 1 : len2 = -1;
867 : 1 : len = asn1_get_length_der (p->value, p->value_len, &len2);
868 : 1 : fprintf (out, " value:0x");
869 [ + - ]: 1 : if (len > 0)
870 [ + + ]: 2 : for (k = 0; k < len; k++)
871 : 1 : fprintf (out, "%02x", (p->value)[k + len2]);
872 : : }
873 : 1 : break;
874 : : case TYPE_TIME:
875 [ + - ]: 4 : if (p->value)
876 : 4 : fprintf (out, " value:%s", p->value);
877 : 4 : break;
878 : : case TYPE_BOOLEAN:
879 [ + + ]: 5 : if (p->value)
880 : : {
881 [ + - ]: 1 : if (p->value[0] == 'T')
882 : 1 : fprintf (out, " value:TRUE");
883 [ # # ]: 0 : else if (p->value[0] == 'F')
884 : 0 : fprintf (out, " value:FALSE");
885 : : }
886 : 5 : break;
887 : : case TYPE_BIT_STRING:
888 [ + - ]: 3 : if (p->value)
889 : : {
890 : 3 : len2 = -1;
891 : 3 : len = asn1_get_length_der (p->value, p->value_len, &len2);
892 [ + - ]: 3 : if (len > 0)
893 : : {
894 : 3 : fprintf (out, " value(%i):",
895 : 3 : (len - 1) * 8 - (p->value[len2]));
896 [ + + ]: 531 : for (k = 1; k < len; k++)
897 : 528 : fprintf (out, "%02x", (p->value)[k + len2]);
898 : : }
899 : : }
900 : 3 : break;
901 : : case TYPE_OCTET_STRING:
902 [ + + ]: 15 : if (p->value)
903 : : {
904 : 5 : len2 = -1;
905 : 5 : len = asn1_get_length_der (p->value, p->value_len, &len2);
906 : 5 : fprintf (out, " value:");
907 [ + + ]: 5 : if (len > 0)
908 [ + + ]: 25 : for (k = 0; k < len; k++)
909 : 21 : fprintf (out, "%02x", (p->value)[k + len2]);
910 : : }
911 : 15 : break;
912 : : case TYPE_GENERALSTRING:
913 [ + - ]: 2 : if (p->value)
914 : : {
915 : 2 : len2 = -1;
916 : 2 : len = asn1_get_length_der (p->value, p->value_len, &len2);
917 : 2 : fprintf (out, " value:");
918 [ + - ]: 2 : if (len > 0)
919 [ + + ]: 12 : for (k = 0; k < len; k++)
920 : 10 : fprintf (out, "%02x", (p->value)[k + len2]);
921 : : }
922 : 2 : break;
923 : : case TYPE_OBJECT_ID:
924 [ + + ]: 50 : if (p->value)
925 : 34 : fprintf (out, " value:%s", p->value);
926 : 50 : break;
927 : : case TYPE_ANY:
928 [ + + ]: 39 : if (p->value)
929 : : {
930 : 27 : len3 = -1;
931 : 27 : len2 = asn1_get_length_der (p->value, p->value_len, &len3);
932 : 27 : fprintf (out, " value:");
933 [ + - ]: 27 : if (len2 > 0)
934 [ + + ]: 311 : for (k = 0; k < len2; k++)
935 : 284 : fprintf (out, "%02x", (p->value)[k + len3]);
936 : : }
937 : 39 : break;
938 : : case TYPE_SET:
939 : : case TYPE_SET_OF:
940 : : case TYPE_CHOICE:
941 : : case TYPE_DEFINITIONS:
942 : : case TYPE_SEQUENCE_OF:
943 : : case TYPE_SEQUENCE:
944 : : case TYPE_NULL:
945 : 99 : break;
946 : : default:
947 : 0 : break;
948 : : }
949 : : }
950 : :
951 [ + + ]: 331 : if (mode == ASN1_PRINT_ALL)
952 : : {
953 [ + + ]: 222 : if (p->type & 0x1FFFFF00)
954 : : {
955 : 75 : fprintf (out, " attr:");
956 [ + + ]: 75 : if (p->type & CONST_UNIVERSAL)
957 : 9 : fprintf (out, "UNIVERSAL,");
958 [ - + ]: 75 : if (p->type & CONST_PRIVATE)
959 : 0 : fprintf (out, "PRIVATE,");
960 [ + + ]: 75 : if (p->type & CONST_APPLICATION)
961 : 1 : fprintf (out, "APPLICATION,");
962 [ + + ]: 75 : if (p->type & CONST_EXPLICIT)
963 : 5 : fprintf (out, "EXPLICIT,");
964 [ + + ]: 75 : if (p->type & CONST_IMPLICIT)
965 : 26 : fprintf (out, "IMPLICIT,");
966 [ + + ]: 75 : if (p->type & CONST_TAG)
967 : 28 : fprintf (out, "TAG,");
968 [ + + ]: 75 : if (p->type & CONST_DEFAULT)
969 : 8 : fprintf (out, "DEFAULT,");
970 [ + + ]: 75 : if (p->type & CONST_TRUE)
971 : 1 : fprintf (out, "TRUE,");
972 [ - + ]: 75 : if (p->type & CONST_FALSE)
973 : 0 : fprintf (out, "FALSE,");
974 [ + + ]: 75 : if (p->type & CONST_LIST)
975 : 4 : fprintf (out, "LIST,");
976 [ + + ]: 75 : if (p->type & CONST_MIN_MAX)
977 : 3 : fprintf (out, "MIN_MAX,");
978 [ + + ]: 75 : if (p->type & CONST_OPTION)
979 : 9 : fprintf (out, "OPTION,");
980 [ - + ]: 75 : if (p->type & CONST_1_PARAM)
981 : 0 : fprintf (out, "1_PARAM,");
982 [ + + ]: 75 : if (p->type & CONST_SIZE)
983 : 3 : fprintf (out, "SIZE,");
984 [ + + ]: 75 : if (p->type & CONST_DEFINED_BY)
985 : 1 : fprintf (out, "DEF_BY,");
986 [ + + ]: 75 : if (p->type & CONST_GENERALIZED)
987 : 1 : fprintf (out, "GENERALIZED,");
988 [ + + ]: 75 : if (p->type & CONST_UTC)
989 : 1 : fprintf (out, "UTC,");
990 [ - + ]: 75 : if (p->type & CONST_SET)
991 : 0 : fprintf (out, "SET,");
992 [ - + ]: 75 : if (p->type & CONST_NOT_USED)
993 : 0 : fprintf (out, "NOT_USED,");
994 [ - + ]: 75 : if (p->type & CONST_ASSIGN)
995 : 0 : fprintf (out, "ASSIGNMENT,");
996 : : }
997 : : }
998 : :
999 [ + + ]: 331 : if (mode == ASN1_PRINT_ALL)
1000 : : {
1001 : 222 : fprintf (out, "\n");
1002 : : }
1003 : : else
1004 : : {
1005 [ + + ]: 109 : switch (type_field (p->type))
1006 : : {
1007 : : case TYPE_CONSTANT:
1008 : : case TYPE_TAG:
1009 : : case TYPE_SIZE:
1010 : 17 : break;
1011 : : default:
1012 : 92 : fprintf (out, "\n");
1013 : : }
1014 : : }
1015 : :
1016 [ + + ]: 331 : if (p->down)
1017 : : {
1018 : 130 : p = p->down;
1019 : 130 : indent += 2;
1020 : : }
1021 [ - + ]: 201 : else if (p == root)
1022 : : {
1023 : 0 : p = NULL;
1024 : 0 : break;
1025 : : }
1026 [ + + ]: 201 : else if (p->right)
1027 : 108 : p = p->right;
1028 : : else
1029 : : {
1030 : : while (1)
1031 : : {
1032 : 130 : p = _asn1_find_up (p);
1033 [ + + ]: 130 : if (p == root)
1034 : : {
1035 : 26 : p = NULL;
1036 : 26 : break;
1037 : : }
1038 : 104 : indent -= 2;
1039 [ + + ]: 104 : if (p->right)
1040 : : {
1041 : 67 : p = p->right;
1042 : 67 : break;
1043 : : }
1044 : 37 : }
1045 : : }
1046 : : }
1047 : : }
1048 : :
1049 : :
1050 : :
1051 : : /**
1052 : : * asn1_number_of_elements:
1053 : : * @element: pointer to the root of an ASN1 structure.
1054 : : * @name: the name of a sub-structure of ROOT.
1055 : : * @num: pointer to an integer where the result will be stored
1056 : : *
1057 : : * Counts the number of elements of a sub-structure called NAME with
1058 : : * names equal to "?1","?2", ...
1059 : : *
1060 : : * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
1061 : : * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
1062 : : **/
1063 : : asn1_retCode
1064 : 1 : asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num)
1065 : : {
1066 : : ASN1_TYPE node, p;
1067 : :
1068 [ - + ]: 1 : if (num == NULL)
1069 : 0 : return ASN1_GENERIC_ERROR;
1070 : :
1071 : 1 : *num = 0;
1072 : :
1073 : 1 : node = asn1_find_node (element, name);
1074 [ - + ]: 1 : if (node == NULL)
1075 : 0 : return ASN1_ELEMENT_NOT_FOUND;
1076 : :
1077 : 1 : p = node->down;
1078 : :
1079 [ + + ]: 4 : while (p)
1080 : : {
1081 [ + + ][ + - ]: 3 : if ((p->name) && (p->name[0] == '?'))
1082 : 2 : (*num)++;
1083 : 3 : p = p->right;
1084 : : }
1085 : :
1086 : 1 : return ASN1_SUCCESS;
1087 : : }
1088 : :
1089 : :
1090 : : /**
1091 : : * asn1_find_structure_from_oid:
1092 : : * @definitions: ASN1 definitions
1093 : : * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1094 : : *
1095 : : * Search the structure that is defined just after an OID definition.
1096 : : *
1097 : : * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1098 : : * constant string that contains the element name defined just after
1099 : : * the OID.
1100 : : **/
1101 : : const char *
1102 : 3 : asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue)
1103 : : {
1104 : : char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
1105 : : char value[ASN1_MAX_NAME_SIZE];
1106 : : ASN1_TYPE p;
1107 : : int len;
1108 : : asn1_retCode result;
1109 : :
1110 [ + - ][ - + ]: 3 : if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL))
1111 : 0 : return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1112 : :
1113 : :
1114 : 3 : strcpy (definitionsName, definitions->name);
1115 : 3 : strcat (definitionsName, ".");
1116 : :
1117 : : /* search the OBJECT_ID into definitions */
1118 : 3 : p = definitions->down;
1119 [ + + ]: 96 : while (p)
1120 : : {
1121 [ + + ][ + + ]: 95 : if ((type_field (p->type) == TYPE_OBJECT_ID) &&
1122 : 20 : (p->type & CONST_ASSIGN))
1123 : : {
1124 : 14 : strcpy (name, definitionsName);
1125 : 14 : strcat (name, p->name);
1126 : :
1127 : 14 : len = ASN1_MAX_NAME_SIZE;
1128 : 14 : result = asn1_read_value (definitions, name, value, &len);
1129 : :
1130 [ + - ][ + + ]: 14 : if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
1131 : : {
1132 : 2 : p = p->right;
1133 [ + + ]: 2 : if (p == NULL) /* reach the end of ASN1 definitions */
1134 : 1 : return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1135 : :
1136 : 1 : return p->name;
1137 : : }
1138 : : }
1139 : 93 : p = p->right;
1140 : : }
1141 : :
1142 : 3 : return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1143 : : }
1144 : :
1145 : : /**
1146 : : * asn1_copy_node:
1147 : : * @dst: Destination ASN1_TYPE node.
1148 : : * @dst_name: Field name in destination node.
1149 : : * @src: Source ASN1_TYPE node.
1150 : : * @src_name: Field name in source node.
1151 : : *
1152 : : * Create a deep copy of a ASN1_TYPE variable.
1153 : : *
1154 : : * Returns: Return %ASN1_SUCCESS on success.
1155 : : **/
1156 : : asn1_retCode
1157 : 0 : asn1_copy_node (ASN1_TYPE dst, const char *dst_name,
1158 : : ASN1_TYPE src, const char *src_name)
1159 : : {
1160 : : /* FIXME: rewrite using copy_structure().
1161 : : * It seems quite hard to do.
1162 : : */
1163 : : int result;
1164 : : ASN1_TYPE dst_node;
1165 : 0 : void *data = NULL;
1166 : 0 : int size = 0;
1167 : :
1168 : 0 : result = asn1_der_coding (src, src_name, NULL, &size, NULL);
1169 [ # # ]: 0 : if (result != ASN1_MEM_ERROR)
1170 : 0 : return result;
1171 : :
1172 : 0 : data = _asn1_malloc (size);
1173 [ # # ]: 0 : if (data == NULL)
1174 : 0 : return ASN1_MEM_ERROR;
1175 : :
1176 : 0 : result = asn1_der_coding (src, src_name, data, &size, NULL);
1177 [ # # ]: 0 : if (result != ASN1_SUCCESS)
1178 : : {
1179 : 0 : _asn1_free (data);
1180 : 0 : return result;
1181 : : }
1182 : :
1183 : 0 : dst_node = asn1_find_node (dst, dst_name);
1184 [ # # ]: 0 : if (dst_node == NULL)
1185 : : {
1186 : 0 : _asn1_free (data);
1187 : 0 : return ASN1_ELEMENT_NOT_FOUND;
1188 : : }
1189 : :
1190 : 0 : result = asn1_der_decoding (&dst_node, data, size, NULL);
1191 : :
1192 : 0 : _asn1_free (data);
1193 : :
1194 : 0 : return result;
1195 : : }
|