Coverage Report

Created: 2023-06-07 06:11

/src/libtasn1/lib/structure.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2002-2023 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_single_node                     */
41
/* Description: creates a new NODE_ASN element.       */
42
/* Parameters:                                        */
43
/*   type: type of the new element (see ASN1_ETYPE_         */
44
/*         and CONST_ constants).                     */
45
/* Return: pointer to the new element.                */
46
/******************************************************/
47
asn1_node
48
_asn1_add_single_node (unsigned int type)
49
37.1k
{
50
37.1k
  asn1_node punt;
51
52
37.1k
  punt = calloc (1, sizeof (struct asn1_node_st));
53
37.1k
  if (punt == NULL)
54
0
    return NULL;
55
56
37.1k
  punt->type = type;
57
58
37.1k
  return punt;
59
37.1k
}
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_node
71
_asn1_find_left (asn1_node_const node)
72
440
{
73
440
  if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
74
440
    return NULL;
75
76
0
  return node->left;
77
440
}
78
79
80
int
81
_asn1_create_static_structure (asn1_node_const pointer,
82
             char *output_file_name, char *vector_name)
83
0
{
84
0
  FILE *file;
85
0
  asn1_node_const p;
86
0
  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_static_node %s[] = {\n", vector_name);
100
101
0
  p = pointer;
102
103
0
  while (p)
104
0
    {
105
0
      fprintf (file, "  { ");
106
107
0
      if (p->name[0] != 0)
108
0
  fprintf (file, "\"%s\", ", p->name);
109
0
      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
0
      else
123
0
  fprintf (file, "NULL },\n");
124
125
0
      if (p->down)
126
0
  {
127
0
    p = p->down;
128
0
  }
129
0
      else if (p->right)
130
0
  {
131
0
    p = p->right;
132
0
  }
133
0
      else
134
0
  {
135
0
    while (1)
136
0
      {
137
0
        p = _asn1_find_up (p);
138
0
        if (p == pointer)
139
0
    {
140
0
      p = NULL;
141
0
      break;
142
0
    }
143
0
        if (p->right)
144
0
    {
145
0
      p = p->right;
146
0
      break;
147
0
    }
148
0
      }
149
0
  }
150
0
    }
151
152
0
  fprintf (file, "  { NULL, 0, NULL }\n};\n");
153
154
0
  fclose (file);
155
156
0
  return ASN1_SUCCESS;
157
0
}
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 NULL,
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
int
177
asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
178
     char *errorDescription)
179
0
{
180
0
  asn1_node p, p_last = NULL;
181
0
  unsigned long k;
182
0
  int move;
183
0
  int result;
184
0
  unsigned int type;
185
0
  list_type *e_list = NULL;
186
187
0
  if (errorDescription)
188
0
    errorDescription[0] = 0;
189
190
0
  if (*definitions != NULL)
191
0
    return ASN1_ELEMENT_NOT_EMPTY;
192
193
0
  move = UP;
194
195
0
  for (k = 0; array[k].value || array[k].type || array[k].name; k++)
196
0
    {
197
0
      type = convert_old_type (array[k].type);
198
199
0
      p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN));
200
0
      if (array[k].name)
201
0
  _asn1_set_name (p, array[k].name);
202
0
      if (array[k].value)
203
0
  _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
204
205
0
      if (*definitions == NULL)
206
0
  *definitions = p;
207
208
0
      if (move == DOWN)
209
0
  {
210
0
    if (p_last && p_last->down)
211
0
      _asn1_delete_structure (e_list, &p_last->down, 0);
212
0
    _asn1_set_down (p_last, p);
213
0
  }
214
0
      else if (move == RIGHT)
215
0
  {
216
0
    if (p_last && p_last->right)
217
0
      _asn1_delete_structure (e_list, &p_last->right, 0);
218
0
    _asn1_set_right (p_last, p);
219
0
  }
220
221
0
      p_last = p;
222
223
0
      if (type & CONST_DOWN)
224
0
  move = DOWN;
225
0
      else if (type & CONST_RIGHT)
226
0
  move = RIGHT;
227
0
      else
228
0
  {
229
0
    while (p_last != *definitions)
230
0
      {
231
0
        p_last = _asn1_find_up (p_last);
232
233
0
        if (p_last == NULL)
234
0
    break;
235
236
0
        if (p_last->type & CONST_RIGHT)
237
0
    {
238
0
      p_last->type &= ~CONST_RIGHT;
239
0
      move = RIGHT;
240
0
      break;
241
0
    }
242
0
      }     /* while */
243
0
  }
244
0
    }       /* while */
245
246
0
  if (p_last == *definitions)
247
0
    {
248
0
      result = _asn1_check_identifier (*definitions);
249
0
      if (result == ASN1_SUCCESS)
250
0
  {
251
0
    _asn1_change_integer_value (*definitions);
252
0
    result = _asn1_expand_object_id (&e_list, *definitions);
253
0
  }
254
0
    }
255
0
  else
256
0
    {
257
0
      result = ASN1_ARRAY_ERROR;
258
0
    }
259
260
0
  if (errorDescription != NULL)
261
0
    {
262
0
      if (result == ASN1_IDENTIFIER_NOT_FOUND)
263
0
  {
264
0
    Estrcpy (errorDescription, ":: identifier '");
265
0
    Estrcat (errorDescription, _asn1_identifierMissing);
266
0
    Estrcat (errorDescription, "' not found");
267
0
  }
268
0
      else
269
0
  errorDescription[0] = 0;
270
0
    }
271
272
0
  if (result != ASN1_SUCCESS)
273
0
    {
274
0
      _asn1_delete_list_and_nodes (e_list);
275
0
      *definitions = NULL;
276
0
    }
277
0
  else
278
0
    _asn1_delete_list (e_list);
279
280
0
  return result;
281
0
}
282
283
/**
284
 * asn1_delete_structure:
285
 * @structure: pointer to the structure that you want to delete.
286
 *
287
 * Deletes the structure *@structure.  At the end, *@structure is set
288
 * to NULL.
289
 *
290
 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
291
 *   *@structure was NULL.
292
 **/
293
int
294
asn1_delete_structure (asn1_node * structure)
295
440
{
296
440
  return _asn1_delete_structure (NULL, structure, 0);
297
440
}
298
299
/**
300
 * asn1_delete_structure2:
301
 * @structure: pointer to the structure that you want to delete.
302
 * @flags: additional flags (see %ASN1_DELETE_FLAG_ZEROIZE)
303
 *
304
 * Deletes the structure *@structure.  At the end, *@structure is set
305
 * to NULL.
306
 *
307
 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
308
 *   *@structure was NULL.
309
 **/
310
int
311
asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
312
0
{
313
0
  return _asn1_delete_structure (NULL, structure, flags);
314
0
}
315
316
int
317
_asn1_delete_structure (list_type * e_list, asn1_node * structure,
318
      unsigned int flags)
319
440
{
320
440
  asn1_node p, p2, p3;
321
322
440
  if (*structure == NULL)
323
0
    return ASN1_ELEMENT_NOT_FOUND;
324
325
440
  p = *structure;
326
39.1k
  while (p)
327
38.7k
    {
328
38.7k
      if (p->down)
329
19.1k
  {
330
19.1k
    p = p->down;
331
19.1k
  }
332
19.5k
      else
333
19.5k
  {     /* no down */
334
19.5k
    p2 = p->right;
335
19.5k
    if (p != *structure)
336
19.1k
      {
337
19.1k
        p3 = _asn1_find_up (p);
338
19.1k
        _asn1_set_down (p3, p2);
339
19.1k
        if (e_list)
340
0
    _asn1_delete_node_from_list (e_list, p);
341
19.1k
        _asn1_remove_node (p, flags);
342
19.1k
        p = p3;
343
19.1k
      }
344
440
    else
345
440
      {     /* p==root */
346
440
        p3 = _asn1_find_left (p);
347
440
        if (!p3)
348
440
    {
349
440
      p3 = _asn1_find_up (p);
350
440
      if (p3)
351
0
        _asn1_set_down (p3, p2);
352
440
      else
353
440
        {
354
440
          if (p->right)
355
0
      p->right->left = NULL;
356
440
        }
357
440
    }
358
0
        else
359
0
    _asn1_set_right (p3, p2);
360
440
        if (e_list)
361
0
    _asn1_delete_node_from_list (e_list, p);
362
440
        _asn1_remove_node (p, flags);
363
440
        p = NULL;
364
440
      }
365
19.5k
  }
366
38.7k
    }
367
368
440
  *structure = NULL;
369
440
  return ASN1_SUCCESS;
370
440
}
371
372
373
/**
374
 * asn1_delete_element:
375
 * @structure: pointer to the structure that contains the element you
376
 *   want to delete.
377
 * @element_name: element's name you want to delete.
378
 *
379
 * Deletes the element named *@element_name inside *@structure.
380
 *
381
 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
382
 *   the @element_name was not found.
383
 **/
384
int
385
asn1_delete_element (asn1_node structure, const char *element_name)
386
0
{
387
0
  asn1_node p2, p3, source_node;
388
389
0
  source_node = asn1_find_node (structure, element_name);
390
391
0
  if (source_node == NULL)
392
0
    return ASN1_ELEMENT_NOT_FOUND;
393
394
0
  p2 = source_node->right;
395
0
  p3 = _asn1_find_left (source_node);
396
0
  if (!p3)
397
0
    {
398
0
      p3 = _asn1_find_up (source_node);
399
0
      if (p3)
400
0
  _asn1_set_down (p3, p2);
401
0
      else if (source_node->right)
402
0
  source_node->right->left = NULL;
403
0
    }
404
0
  else
405
0
    _asn1_set_right (p3, p2);
406
407
0
  return asn1_delete_structure (&source_node);
408
0
}
409
410
#ifndef __clang_analyzer__
411
asn1_node
412
_asn1_copy_structure3 (asn1_node_const source_node)
413
0
{
414
0
  asn1_node_const p_s;
415
0
  asn1_node dest_node, p_d, p_d_prev;
416
0
  int move;
417
418
0
  if (source_node == NULL)
419
0
    return NULL;
420
421
0
  dest_node = _asn1_add_single_node (source_node->type);
422
0
  if (dest_node == NULL)
423
0
    return dest_node;
424
425
0
  p_s = source_node;
426
0
  p_d = dest_node;
427
428
0
  move = DOWN;
429
430
0
  do
431
0
    {
432
0
      if (move != UP)
433
0
  {
434
0
    if (p_s->name[0] != 0)
435
0
      _asn1_cpy_name (p_d, p_s);
436
0
    if (p_s->value)
437
0
      _asn1_set_value (p_d, p_s->value, p_s->value_len);
438
0
    if (p_s->down)
439
0
      {
440
0
        p_s = p_s->down;
441
0
        p_d_prev = p_d;
442
0
        p_d = _asn1_add_single_node (p_s->type);
443
0
        _asn1_set_down (p_d_prev, p_d);
444
0
        continue;
445
0
      }
446
0
    p_d->start = p_s->start;
447
0
    p_d->end = p_s->end;
448
0
  }
449
450
0
      if (p_s == source_node)
451
0
  break;
452
453
0
      if (p_s->right)
454
0
  {
455
0
    move = RIGHT;
456
0
    p_s = p_s->right;
457
0
    p_d_prev = p_d;
458
0
    p_d = _asn1_add_single_node (p_s->type);
459
0
    _asn1_set_right (p_d_prev, p_d);
460
0
  }
461
0
      else
462
0
  {
463
0
    move = UP;
464
0
    p_s = _asn1_find_up (p_s);
465
0
    p_d = _asn1_find_up (p_d);
466
0
  }
467
0
    }
468
0
  while (p_s != source_node);
469
0
  return dest_node;
470
0
}
471
#else
472
473
/* Non-production code */
474
asn1_node
475
_asn1_copy_structure3 (asn1_node_const source_node)
476
{
477
  return NULL;
478
}
479
#endif /* __clang_analyzer__ */
480
481
482
static asn1_node
483
_asn1_copy_structure2 (asn1_node_const root, const char *source_name)
484
0
{
485
0
  asn1_node source_node;
486
487
0
  source_node = asn1_find_node (root, source_name);
488
489
0
  return _asn1_copy_structure3 (source_node);
490
491
0
}
492
493
494
static int
495
_asn1_type_choice_config (asn1_node node)
496
0
{
497
0
  asn1_node p, p2, p3, p4;
498
0
  int move, tlen;
499
500
0
  if (node == NULL)
501
0
    return ASN1_ELEMENT_NOT_FOUND;
502
503
0
  p = node;
504
0
  move = DOWN;
505
506
0
  while (!((p == node) && (move == UP)))
507
0
    {
508
0
      if (move != UP)
509
0
  {
510
0
    if ((type_field (p->type) == ASN1_ETYPE_CHOICE)
511
0
        && (p->type & CONST_TAG))
512
0
      {
513
0
        p2 = p->down;
514
0
        while (p2)
515
0
    {
516
0
      if (type_field (p2->type) != ASN1_ETYPE_TAG)
517
0
        {
518
0
          p2->type |= CONST_TAG;
519
0
          p3 = _asn1_find_left (p2);
520
0
          while (p3)
521
0
      {
522
0
        if (type_field (p3->type) == ASN1_ETYPE_TAG)
523
0
          {
524
0
            p4 = _asn1_add_single_node (p3->type);
525
0
            tlen = _asn1_strlen (p3->value);
526
0
            if (tlen > 0)
527
0
        _asn1_set_value (p4, p3->value, tlen + 1);
528
0
            _asn1_set_right (p4, p2->down);
529
0
            _asn1_set_down (p2, p4);
530
0
          }
531
0
        p3 = _asn1_find_left (p3);
532
0
      }
533
0
        }
534
0
      p2 = p2->right;
535
0
    }
536
0
        p->type &= ~(CONST_TAG);
537
0
        p2 = p->down;
538
0
        while (p2)
539
0
    {
540
0
      p3 = p2->right;
541
0
      if (type_field (p2->type) == ASN1_ETYPE_TAG)
542
0
        asn1_delete_structure (&p2);
543
0
      p2 = p3;
544
0
    }
545
0
      }
546
0
    move = DOWN;
547
0
  }
548
0
      else
549
0
  move = RIGHT;
550
551
0
      if (move == DOWN)
552
0
  {
553
0
    if (p->down)
554
0
      p = p->down;
555
0
    else
556
0
      move = RIGHT;
557
0
  }
558
559
0
      if (p == node)
560
0
  {
561
0
    move = UP;
562
0
    continue;
563
0
  }
564
565
0
      if (move == RIGHT)
566
0
  {
567
0
    if (p->right)
568
0
      p = p->right;
569
0
    else
570
0
      move = UP;
571
0
  }
572
0
      if (move == UP)
573
0
  p = _asn1_find_up (p);
574
0
    }
575
576
0
  return ASN1_SUCCESS;
577
0
}
578
579
580
static int
581
_asn1_expand_identifier (asn1_node * node, asn1_node_const root)
582
0
{
583
0
  asn1_node p, p2, p3;
584
0
  char name2[ASN1_MAX_NAME_SIZE + 2];
585
0
  int move;
586
587
0
  if (node == NULL)
588
0
    return ASN1_ELEMENT_NOT_FOUND;
589
590
0
  p = *node;
591
0
  move = DOWN;
592
593
0
  while (!((p == *node) && (move == UP)))
594
0
    {
595
0
      if (move != UP)
596
0
  {
597
0
    if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
598
0
      {
599
0
        snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
600
0
        p2 = _asn1_copy_structure2 (root, name2);
601
0
        if (p2 == NULL)
602
0
    {
603
0
      return ASN1_IDENTIFIER_NOT_FOUND;
604
0
    }
605
0
        _asn1_cpy_name (p2, p);
606
0
        p2->right = p->right;
607
0
        p2->left = p->left;
608
0
        if (p->right)
609
0
    p->right->left = p2;
610
0
        p3 = p->down;
611
0
        if (p3)
612
0
    {
613
0
      while (p3->right)
614
0
        p3 = p3->right;
615
0
      _asn1_set_right (p3, p2->down);
616
0
      _asn1_set_down (p2, p->down);
617
0
    }
618
619
0
        p3 = _asn1_find_left (p);
620
0
        if (p3)
621
0
    _asn1_set_right (p3, p2);
622
0
        else
623
0
    {
624
0
      p3 = _asn1_find_up (p);
625
0
      if (p3)
626
0
        _asn1_set_down (p3, p2);
627
0
      else
628
0
        {
629
0
          p2->left = NULL;
630
0
        }
631
0
    }
632
633
0
        if (p->type & CONST_SIZE)
634
0
    p2->type |= CONST_SIZE;
635
0
        if (p->type & CONST_TAG)
636
0
    p2->type |= CONST_TAG;
637
0
        if (p->type & CONST_OPTION)
638
0
    p2->type |= CONST_OPTION;
639
0
        if (p->type & CONST_DEFAULT)
640
0
    p2->type |= CONST_DEFAULT;
641
0
        if (p->type & CONST_SET)
642
0
    p2->type |= CONST_SET;
643
0
        if (p->type & CONST_NOT_USED)
644
0
    p2->type |= CONST_NOT_USED;
645
646
0
        if (p == *node)
647
0
    *node = p2;
648
0
        _asn1_remove_node (p, 0);
649
0
        p = p2;
650
0
        move = DOWN;
651
0
        continue;
652
0
      }
653
0
    move = DOWN;
654
0
  }
655
0
      else
656
0
  move = RIGHT;
657
658
0
      if (move == DOWN)
659
0
  {
660
0
    if (p->down)
661
0
      p = p->down;
662
0
    else
663
0
      move = RIGHT;
664
0
  }
665
666
0
      if (p == *node)
667
0
  {
668
0
    move = UP;
669
0
    continue;
670
0
  }
671
672
0
      if (move == RIGHT)
673
0
  {
674
0
    if (p->right)
675
0
      p = p->right;
676
0
    else
677
0
      move = UP;
678
0
  }
679
0
      if (move == UP)
680
0
  p = _asn1_find_up (p);
681
0
    }
682
683
0
  return ASN1_SUCCESS;
684
0
}
685
686
687
/**
688
 * asn1_create_element:
689
 * @definitions: pointer to the structure returned by "parser_asn1" function
690
 * @source_name: the name of the type of the new structure (must be
691
 *   inside p_structure).
692
 * @element: pointer to the structure created.
693
 *
694
 * Creates a structure of type @source_name.  Example using
695
 *  "pkix.asn":
696
 *
697
 * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
698
 *
699
 * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
700
 *   @source_name is not known.
701
 **/
702
int
703
asn1_create_element (asn1_node_const definitions, const char *source_name,
704
         asn1_node * element)
705
0
{
706
0
  asn1_node dest_node;
707
0
  int res;
708
709
0
  dest_node = _asn1_copy_structure2 (definitions, source_name);
710
711
0
  if (dest_node == NULL)
712
0
    return ASN1_ELEMENT_NOT_FOUND;
713
714
0
  _asn1_set_name (dest_node, "");
715
716
0
  res = _asn1_expand_identifier (&dest_node, definitions);
717
0
  _asn1_type_choice_config (dest_node);
718
719
0
  *element = dest_node;
720
721
0
  return res;
722
0
}
723
724
725
/**
726
 * asn1_print_structure:
727
 * @out: pointer to the output file (e.g. stdout).
728
 * @structure: pointer to the structure that you want to visit.
729
 * @name: an element of the structure
730
 * @mode: specify how much of the structure to print, can be
731
 *   %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
732
 *   %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
733
 *
734
 * Prints on the @out file descriptor the structure's tree starting
735
 * from the @name element inside the structure @structure.
736
 **/
737
void
738
asn1_print_structure (FILE * out, asn1_node_const structure, const char *name,
739
          int mode)
740
0
{
741
0
  asn1_node_const p, root;
742
0
  int k, indent = 0, len, len2, len3;
743
744
0
  if (out == NULL)
745
0
    return;
746
747
0
  root = asn1_find_node (structure, name);
748
749
0
  if (root == NULL)
750
0
    return;
751
752
0
  p = root;
753
0
  while (p)
754
0
    {
755
0
      if (mode == ASN1_PRINT_ALL)
756
0
  {
757
0
    for (k = 0; k < indent; k++)
758
0
      fprintf (out, " ");
759
0
    fprintf (out, "name:");
760
0
    if (p->name[0] != 0)
761
0
      fprintf (out, "%s  ", p->name);
762
0
    else
763
0
      fprintf (out, "NULL  ");
764
0
  }
765
0
      else
766
0
  {
767
0
    switch (type_field (p->type))
768
0
      {
769
0
      case ASN1_ETYPE_CONSTANT:
770
0
      case ASN1_ETYPE_TAG:
771
0
      case ASN1_ETYPE_SIZE:
772
0
        break;
773
0
      default:
774
0
        for (k = 0; k < indent; k++)
775
0
    fprintf (out, " ");
776
0
        fprintf (out, "name:");
777
0
        if (p->name[0] != 0)
778
0
    fprintf (out, "%s  ", p->name);
779
0
        else
780
0
    fprintf (out, "NULL  ");
781
0
      }
782
0
  }
783
784
0
      if (mode != ASN1_PRINT_NAME)
785
0
  {
786
0
    unsigned type = type_field (p->type);
787
0
    switch (type)
788
0
      {
789
0
      case ASN1_ETYPE_CONSTANT:
790
0
        if (mode == ASN1_PRINT_ALL)
791
0
    fprintf (out, "type:CONST");
792
0
        break;
793
0
      case ASN1_ETYPE_TAG:
794
0
        if (mode == ASN1_PRINT_ALL)
795
0
    fprintf (out, "type:TAG");
796
0
        break;
797
0
      case ASN1_ETYPE_SIZE:
798
0
        if (mode == ASN1_PRINT_ALL)
799
0
    fprintf (out, "type:SIZE");
800
0
        break;
801
0
      case ASN1_ETYPE_DEFAULT:
802
0
        fprintf (out, "type:DEFAULT");
803
0
        break;
804
0
      case ASN1_ETYPE_IDENTIFIER:
805
0
        fprintf (out, "type:IDENTIFIER");
806
0
        break;
807
0
      case ASN1_ETYPE_ANY:
808
0
        fprintf (out, "type:ANY");
809
0
        break;
810
0
      case ASN1_ETYPE_CHOICE:
811
0
        fprintf (out, "type:CHOICE");
812
0
        break;
813
0
      case ASN1_ETYPE_DEFINITIONS:
814
0
        fprintf (out, "type:DEFINITIONS");
815
0
        break;
816
0
      CASE_HANDLED_ETYPES:
817
0
        fprintf (out, "%s", _asn1_tags[type].desc);
818
0
        break;
819
0
      default:
820
0
        break;
821
0
      }
822
0
  }
823
824
0
      if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
825
0
  {
826
0
    switch (type_field (p->type))
827
0
      {
828
0
      case ASN1_ETYPE_CONSTANT:
829
0
        if (mode == ASN1_PRINT_ALL)
830
0
    if (p->value)
831
0
      fprintf (out, "  value:%s", p->value);
832
0
        break;
833
0
      case ASN1_ETYPE_TAG:
834
0
        if (mode == ASN1_PRINT_ALL)
835
0
    if (p->value)
836
0
      fprintf (out, "  value:%s", p->value);
837
0
        break;
838
0
      case ASN1_ETYPE_SIZE:
839
0
        if (mode == ASN1_PRINT_ALL)
840
0
    if (p->value)
841
0
      fprintf (out, "  value:%s", p->value);
842
0
        break;
843
0
      case ASN1_ETYPE_DEFAULT:
844
0
        if (p->value)
845
0
    fprintf (out, "  value:%s", p->value);
846
0
        else if (p->type & CONST_TRUE)
847
0
    fprintf (out, "  value:TRUE");
848
0
        else if (p->type & CONST_FALSE)
849
0
    fprintf (out, "  value:FALSE");
850
0
        break;
851
0
      case ASN1_ETYPE_IDENTIFIER:
852
0
        if (p->value)
853
0
    fprintf (out, "  value:%s", p->value);
854
0
        break;
855
0
      case ASN1_ETYPE_INTEGER:
856
0
        if (p->value)
857
0
    {
858
0
      len2 = -1;
859
0
      len = asn1_get_length_der (p->value, p->value_len, &len2);
860
0
      fprintf (out, "  value:0x");
861
0
      if (len > 0)
862
0
        for (k = 0; k < len; k++)
863
0
          fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
864
0
    }
865
0
        break;
866
0
      case ASN1_ETYPE_ENUMERATED:
867
0
        if (p->value)
868
0
    {
869
0
      len2 = -1;
870
0
      len = asn1_get_length_der (p->value, p->value_len, &len2);
871
0
      fprintf (out, "  value:0x");
872
0
      if (len > 0)
873
0
        for (k = 0; k < len; k++)
874
0
          fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
875
0
    }
876
0
        break;
877
0
      case ASN1_ETYPE_BOOLEAN:
878
0
        if (p->value)
879
0
    {
880
0
      if (p->value[0] == 'T')
881
0
        fprintf (out, "  value:TRUE");
882
0
      else if (p->value[0] == 'F')
883
0
        fprintf (out, "  value:FALSE");
884
0
    }
885
0
        break;
886
0
      case ASN1_ETYPE_BIT_STRING:
887
0
        if (p->value)
888
0
    {
889
0
      len2 = -1;
890
0
      len = asn1_get_length_der (p->value, p->value_len, &len2);
891
0
      if (len > 0)
892
0
        {
893
0
          fprintf (out, "  value(%i):",
894
0
             (len - 1) * 8 - (p->value[len2]));
895
0
          for (k = 1; k < len; k++)
896
0
      fprintf (out, "%02x",
897
0
         (unsigned) (p->value)[k + len2]);
898
0
        }
899
0
    }
900
0
        break;
901
0
      case ASN1_ETYPE_GENERALIZED_TIME:
902
0
      case ASN1_ETYPE_UTC_TIME:
903
0
        if (p->value)
904
0
    {
905
0
      fprintf (out, "  value:");
906
0
      for (k = 0; k < p->value_len; k++)
907
0
        fprintf (out, "%c", (p->value)[k]);
908
0
    }
909
0
        break;
910
0
      case ASN1_ETYPE_GENERALSTRING:
911
0
      case ASN1_ETYPE_NUMERIC_STRING:
912
0
      case ASN1_ETYPE_IA5_STRING:
913
0
      case ASN1_ETYPE_TELETEX_STRING:
914
0
      case ASN1_ETYPE_PRINTABLE_STRING:
915
0
      case ASN1_ETYPE_UNIVERSAL_STRING:
916
0
      case ASN1_ETYPE_UTF8_STRING:
917
0
      case ASN1_ETYPE_VISIBLE_STRING:
918
0
        if (p->value)
919
0
    {
920
0
      len2 = -1;
921
0
      len = asn1_get_length_der (p->value, p->value_len, &len2);
922
0
      fprintf (out, "  value:");
923
0
      if (len > 0)
924
0
        for (k = 0; k < len; k++)
925
0
          fprintf (out, "%c", (p->value)[k + len2]);
926
0
    }
927
0
        break;
928
0
      case ASN1_ETYPE_BMP_STRING:
929
0
      case ASN1_ETYPE_OCTET_STRING:
930
0
        if (p->value)
931
0
    {
932
0
      len2 = -1;
933
0
      len = asn1_get_length_der (p->value, p->value_len, &len2);
934
0
      fprintf (out, "  value:");
935
0
      if (len > 0)
936
0
        for (k = 0; k < len; k++)
937
0
          fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
938
0
    }
939
0
        break;
940
0
      case ASN1_ETYPE_OBJECT_ID:
941
0
        if (p->value)
942
0
    fprintf (out, "  value:%s", p->value);
943
0
        break;
944
0
      case ASN1_ETYPE_ANY:
945
0
        if (p->value)
946
0
    {
947
0
      len3 = -1;
948
0
      len2 = asn1_get_length_der (p->value, p->value_len, &len3);
949
0
      fprintf (out, "  value:");
950
0
      if (len2 > 0)
951
0
        for (k = 0; k < len2; k++)
952
0
          fprintf (out, "%02x", (unsigned) (p->value)[k + len3]);
953
0
    }
954
0
        break;
955
0
      case ASN1_ETYPE_SET:
956
0
      case ASN1_ETYPE_SET_OF:
957
0
      case ASN1_ETYPE_CHOICE:
958
0
      case ASN1_ETYPE_DEFINITIONS:
959
0
      case ASN1_ETYPE_SEQUENCE_OF:
960
0
      case ASN1_ETYPE_SEQUENCE:
961
0
      case ASN1_ETYPE_NULL:
962
0
        break;
963
0
      default:
964
0
        break;
965
0
      }
966
0
  }
967
968
0
      if (mode == ASN1_PRINT_ALL)
969
0
  {
970
0
    if (p->type & 0x1FFFFF00)
971
0
      {
972
0
        fprintf (out, "  attr:");
973
0
        if (p->type & CONST_UNIVERSAL)
974
0
    fprintf (out, "UNIVERSAL,");
975
0
        if (p->type & CONST_PRIVATE)
976
0
    fprintf (out, "PRIVATE,");
977
0
        if (p->type & CONST_APPLICATION)
978
0
    fprintf (out, "APPLICATION,");
979
0
        if (p->type & CONST_EXPLICIT)
980
0
    fprintf (out, "EXPLICIT,");
981
0
        if (p->type & CONST_IMPLICIT)
982
0
    fprintf (out, "IMPLICIT,");
983
0
        if (p->type & CONST_TAG)
984
0
    fprintf (out, "TAG,");
985
0
        if (p->type & CONST_DEFAULT)
986
0
    fprintf (out, "DEFAULT,");
987
0
        if (p->type & CONST_TRUE)
988
0
    fprintf (out, "TRUE,");
989
0
        if (p->type & CONST_FALSE)
990
0
    fprintf (out, "FALSE,");
991
0
        if (p->type & CONST_LIST)
992
0
    fprintf (out, "LIST,");
993
0
        if (p->type & CONST_MIN_MAX)
994
0
    fprintf (out, "MIN_MAX,");
995
0
        if (p->type & CONST_OPTION)
996
0
    fprintf (out, "OPTION,");
997
0
        if (p->type & CONST_1_PARAM)
998
0
    fprintf (out, "1_PARAM,");
999
0
        if (p->type & CONST_SIZE)
1000
0
    fprintf (out, "SIZE,");
1001
0
        if (p->type & CONST_DEFINED_BY)
1002
0
    fprintf (out, "DEF_BY,");
1003
0
        if (p->type & CONST_GENERALIZED)
1004
0
    fprintf (out, "GENERALIZED,");
1005
0
        if (p->type & CONST_UTC)
1006
0
    fprintf (out, "UTC,");
1007
0
        if (p->type & CONST_SET)
1008
0
    fprintf (out, "SET,");
1009
0
        if (p->type & CONST_NOT_USED)
1010
0
    fprintf (out, "NOT_USED,");
1011
0
        if (p->type & CONST_ASSIGN)
1012
0
    fprintf (out, "ASSIGNMENT,");
1013
0
      }
1014
0
  }
1015
1016
0
      if (mode == ASN1_PRINT_ALL)
1017
0
  {
1018
0
    fprintf (out, "\n");
1019
0
  }
1020
0
      else
1021
0
  {
1022
0
    switch (type_field (p->type))
1023
0
      {
1024
0
      case ASN1_ETYPE_CONSTANT:
1025
0
      case ASN1_ETYPE_TAG:
1026
0
      case ASN1_ETYPE_SIZE:
1027
0
        break;
1028
0
      default:
1029
0
        fprintf (out, "\n");
1030
0
      }
1031
0
  }
1032
1033
0
      if (p->down)
1034
0
  {
1035
0
    p = p->down;
1036
0
    indent += 2;
1037
0
  }
1038
0
      else if (p == root)
1039
0
  {
1040
0
    p = NULL;
1041
0
    break;
1042
0
  }
1043
0
      else if (p->right)
1044
0
  p = p->right;
1045
0
      else
1046
0
  {
1047
0
    while (1)
1048
0
      {
1049
0
        p = _asn1_find_up (p);
1050
0
        if (p == root)
1051
0
    {
1052
0
      p = NULL;
1053
0
      break;
1054
0
    }
1055
0
        indent -= 2;
1056
0
        if (p->right)
1057
0
    {
1058
0
      p = p->right;
1059
0
      break;
1060
0
    }
1061
0
      }
1062
0
  }
1063
0
    }
1064
0
}
1065
1066
1067
1068
/**
1069
 * asn1_number_of_elements:
1070
 * @element: pointer to the root of an ASN1 structure.
1071
 * @name: the name of a sub-structure of ROOT.
1072
 * @num: pointer to an integer where the result will be stored
1073
 *
1074
 * Counts the number of elements of a sub-structure called NAME with
1075
 * names equal to "?1","?2", ...
1076
 *
1077
 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
1078
 *   @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
1079
 **/
1080
int
1081
asn1_number_of_elements (asn1_node_const element, const char *name, int *num)
1082
0
{
1083
0
  asn1_node_const node, p;
1084
1085
0
  if (num == NULL)
1086
0
    return ASN1_GENERIC_ERROR;
1087
1088
0
  *num = 0;
1089
1090
0
  node = asn1_find_node (element, name);
1091
0
  if (node == NULL)
1092
0
    return ASN1_ELEMENT_NOT_FOUND;
1093
1094
0
  p = node->down;
1095
1096
0
  while (p)
1097
0
    {
1098
0
      if (p->name[0] == '?')
1099
0
  (*num)++;
1100
0
      p = p->right;
1101
0
    }
1102
1103
0
  return ASN1_SUCCESS;
1104
0
}
1105
1106
1107
/**
1108
 * asn1_find_structure_from_oid:
1109
 * @definitions: ASN1 definitions
1110
 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1111
 *
1112
 * Search the structure that is defined just after an OID definition.
1113
 *
1114
 * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1115
 *   constant string that contains the element name defined just after
1116
 *   the OID.
1117
 **/
1118
const char *
1119
asn1_find_structure_from_oid (asn1_node_const definitions,
1120
            const char *oidValue)
1121
0
{
1122
0
  char name[2 * ASN1_MAX_NAME_SIZE + 2];
1123
0
  char value[ASN1_MAX_NAME_SIZE];
1124
0
  asn1_node p;
1125
0
  int len;
1126
0
  int result;
1127
0
  const char *definitionsName;
1128
1129
0
  if ((definitions == NULL) || (oidValue == NULL))
1130
0
    return NULL;   /* ASN1_ELEMENT_NOT_FOUND; */
1131
1132
0
  definitionsName = definitions->name;
1133
1134
  /* search the OBJECT_ID into definitions */
1135
0
  p = definitions->down;
1136
0
  while (p)
1137
0
    {
1138
0
      if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
1139
0
    (p->type & CONST_ASSIGN))
1140
0
  {
1141
0
    snprintf (name, sizeof (name), "%s.%s", definitionsName, p->name);
1142
1143
0
    len = ASN1_MAX_NAME_SIZE;
1144
0
    result = asn1_read_value (definitions, name, value, &len);
1145
1146
0
    if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
1147
0
      {
1148
0
        p = p->right;
1149
0
        if (p == NULL) /* reach the end of ASN1 definitions */
1150
0
    return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1151
1152
0
        return p->name;
1153
0
      }
1154
0
  }
1155
0
      p = p->right;
1156
0
    }
1157
1158
0
  return NULL;     /* ASN1_ELEMENT_NOT_FOUND; */
1159
0
}
1160
1161
/**
1162
 * asn1_copy_node:
1163
 * @dst: Destination asn1 node.
1164
 * @dst_name: Field name in destination node.
1165
 * @src: Source asn1 node.
1166
 * @src_name: Field name in source node.
1167
 *
1168
 * Create a deep copy of a asn1_node variable. That
1169
 * function requires @dst to be expanded using asn1_create_element().
1170
 *
1171
 * Returns: Return %ASN1_SUCCESS on success.
1172
 **/
1173
int
1174
asn1_copy_node (asn1_node dst, const char *dst_name,
1175
    asn1_node_const src, const char *src_name)
1176
0
{
1177
0
  int result;
1178
0
  asn1_node dst_node;
1179
0
  void *data = NULL;
1180
0
  int size = 0;
1181
1182
0
  result = asn1_der_coding (src, src_name, NULL, &size, NULL);
1183
0
  if (result != ASN1_MEM_ERROR)
1184
0
    return result;
1185
1186
0
  data = malloc (size);
1187
0
  if (data == NULL)
1188
0
    return ASN1_MEM_ERROR;
1189
1190
0
  result = asn1_der_coding (src, src_name, data, &size, NULL);
1191
0
  if (result != ASN1_SUCCESS)
1192
0
    {
1193
0
      free (data);
1194
0
      return result;
1195
0
    }
1196
1197
0
  dst_node = asn1_find_node (dst, dst_name);
1198
0
  if (dst_node == NULL)
1199
0
    {
1200
0
      free (data);
1201
0
      return ASN1_ELEMENT_NOT_FOUND;
1202
0
    }
1203
1204
0
  result = asn1_der_decoding (&dst_node, data, size, NULL);
1205
1206
0
  free (data);
1207
1208
0
  return result;
1209
0
}
1210
1211
/**
1212
 * asn1_dup_node:
1213
 * @src: Source asn1 node.
1214
 * @src_name: Field name in source node.
1215
 *
1216
 * Create a deep copy of a asn1_node variable. This function
1217
 * will return an exact copy of the provided structure.
1218
 *
1219
 * Returns: Return %NULL on failure.
1220
 **/
1221
asn1_node
1222
asn1_dup_node (asn1_node_const src, const char *src_name)
1223
0
{
1224
0
  return _asn1_copy_structure2 (src, src_name);
1225
0
}