Fix syntax-check nits.
[platform/upstream/libtasn1.git] / lib / parser_aux.c
1 /*
2  * Copyright (C) 2000-2014 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 #include <int.h>
23 #include <hash-pjw-bare.h>
24 #include "parser_aux.h"
25 #include "gstr.h"
26 #include "structure.h"
27 #include "element.h"
28
29 char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1];   /* identifier name not found */
30
31 /***********************************************/
32 /* Type: list_type                             */
33 /* Description: type used in the list during   */
34 /* the structure creation.                     */
35 /***********************************************/
36 typedef struct list_struct
37 {
38   asn1_node node;
39   struct list_struct *next;
40 } list_type;
41
42
43 /* Pointer to the first element of the list */
44 list_type *firstElement = NULL;
45
46 /******************************************************/
47 /* Function : _asn1_add_static_node                   */
48 /* Description: creates a new NODE_ASN element and    */
49 /* puts it in the list pointed by firstElement.       */
50 /* Parameters:                                        */
51 /*   type: type of the new element (see ASN1_ETYPE_   */
52 /*         and CONST_ constants).                     */
53 /* Return: pointer to the new element.                */
54 /******************************************************/
55 asn1_node
56 _asn1_add_static_node (unsigned int type)
57 {
58   list_type *listElement;
59   asn1_node punt;
60
61   punt = calloc (1, sizeof (struct asn1_node_st));
62   if (punt == NULL)
63     return NULL;
64
65   listElement = malloc (sizeof (list_type));
66   if (listElement == NULL)
67     {
68       free (punt);
69       return NULL;
70     }
71
72   listElement->node = punt;
73   listElement->next = firstElement;
74   firstElement = listElement;
75
76   punt->type = type;
77
78   return punt;
79 }
80
81 /**
82  * asn1_find_node:
83  * @pointer: NODE_ASN element pointer.
84  * @name: null terminated string with the element's name to find.
85  *
86  * Searches for an element called @name starting from @pointer.  The
87  * name is composed by differents identifiers separated by dots.  When
88  * *@pointer has a name, the first identifier must be the name of
89  * *@pointer, otherwise it must be the name of one child of *@pointer.
90  *
91  * Returns: the search result, or %NULL if not found.
92  **/
93 asn1_node
94 asn1_find_node (asn1_node pointer, const char *name)
95 {
96   asn1_node p;
97   char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
98   const char *n_start;
99   unsigned int nsize;
100   unsigned int nhash;
101
102   if (pointer == NULL)
103     return NULL;
104
105   if (name == NULL)
106     return NULL;
107
108   p = pointer;
109   n_start = name;
110
111   if (p->name[0] != 0)
112     {                           /* has *pointer got a name ? */
113       n_end = strchr (n_start, '.');    /* search the first dot */
114       if (n_end)
115         {
116           nsize = n_end - n_start;
117           memcpy (n, n_start, nsize);
118           n[nsize] = 0;
119           n_start = n_end;
120           n_start++;
121
122           nhash = hash_pjw_bare (n, nsize);
123         }
124       else
125         {
126           nsize = _asn1_str_cpy (n, sizeof (n), n_start);
127           nhash = hash_pjw_bare (n, nsize);
128
129           n_start = NULL;
130         }
131
132       while (p)
133         {
134           if (nhash == p->name_hash && (!strcmp (p->name, n)))
135             break;
136           else
137             p = p->right;
138         }                       /* while */
139
140       if (p == NULL)
141         return NULL;
142     }
143   else
144     {                           /* *pointer doesn't have a name */
145       if (n_start[0] == 0)
146         return p;
147     }
148
149   while (n_start)
150     {                           /* Has the end of NAME been reached? */
151       n_end = strchr (n_start, '.');    /* search the next dot */
152       if (n_end)
153         {
154           nsize = n_end - n_start;
155           memcpy (n, n_start, nsize);
156           n[nsize] = 0;
157           n_start = n_end;
158           n_start++;
159
160           nhash = hash_pjw_bare (n, nsize);
161         }
162       else
163         {
164           nsize = _asn1_str_cpy (n, sizeof (n), n_start);
165           nhash = hash_pjw_bare (n, nsize);
166           n_start = NULL;
167         }
168
169       if (p->down == NULL)
170         return NULL;
171
172       p = p->down;
173
174       /* The identifier "?LAST" indicates the last element
175          in the right chain. */
176       if (!strcmp (n, "?LAST"))
177         {
178           if (p == NULL)
179             return NULL;
180           while (p->right)
181             p = p->right;
182         }
183       else
184         {                       /* no "?LAST" */
185           while (p)
186             {
187               if (p->name_hash == nhash && !strcmp (p->name, n))
188                 break;
189               else
190                 p = p->right;
191             }
192           if (p == NULL)
193             return NULL;
194         }
195     }                           /* while */
196
197   return p;
198 }
199
200
201 /******************************************************************/
202 /* Function : _asn1_set_value                                     */
203 /* Description: sets the field VALUE in a NODE_ASN element. The   */
204 /*              previous value (if exist) will be lost            */
205 /* Parameters:                                                    */
206 /*   node: element pointer.                                       */
207 /*   value: pointer to the value that you want to set.            */
208 /*   len: character number of value.                              */
209 /* Return: pointer to the NODE_ASN element.                       */
210 /******************************************************************/
211 asn1_node
212 _asn1_set_value (asn1_node node, const void *value, unsigned int len)
213 {
214   if (node == NULL)
215     return node;
216   if (node->value)
217     {
218       if (node->value != node->small_value)
219         free (node->value);
220       node->value = NULL;
221       node->value_len = 0;
222     }
223
224   if (!len)
225     return node;
226
227   if (len < sizeof (node->small_value))
228     {
229       node->value = node->small_value;
230     }
231   else
232     {
233       node->value = malloc (len);
234       if (node->value == NULL)
235         return NULL;
236     }
237   node->value_len = len;
238
239   memcpy (node->value, value, len);
240   return node;
241 }
242
243 /******************************************************************/
244 /* Function : _asn1_set_value_lv                                  */
245 /* Description: sets the field VALUE in a NODE_ASN element. The   */
246 /*              previous value (if exist) will be lost. The value */
247 /*              given is stored as an length-value format (LV     */
248 /* Parameters:                                                    */
249 /*   node: element pointer.                                       */
250 /*   value: pointer to the value that you want to set.            */
251 /*   len: character number of value.                              */
252 /* Return: pointer to the NODE_ASN element.                       */
253 /******************************************************************/
254 asn1_node
255 _asn1_set_value_lv (asn1_node node, const void *value, unsigned int len)
256 {
257   int len2;
258   void *temp;
259
260   if (node == NULL)
261     return node;
262
263   asn1_length_der (len, NULL, &len2);
264   temp = malloc (len + len2);
265   if (temp == NULL)
266     return NULL;
267
268   asn1_octet_der (value, len, temp, &len2);
269   return _asn1_set_value_m (node, temp, len2);
270 }
271
272 /* the same as _asn1_set_value except that it sets an already malloc'ed
273  * value.
274  */
275 asn1_node
276 _asn1_set_value_m (asn1_node node, void *value, unsigned int len)
277 {
278   if (node == NULL)
279     return node;
280
281   if (node->value)
282     {
283       if (node->value != node->small_value)
284         free (node->value);
285       node->value = NULL;
286       node->value_len = 0;
287     }
288
289   if (!len)
290     return node;
291
292   node->value = value;
293   node->value_len = len;
294
295   return node;
296 }
297
298 /******************************************************************/
299 /* Function : _asn1_append_value                                  */
300 /* Description: appends to the field VALUE in a NODE_ASN element. */
301 /*                                                                */
302 /* Parameters:                                                    */
303 /*   node: element pointer.                                       */
304 /*   value: pointer to the value that you want to be appended.    */
305 /*   len: character number of value.                              */
306 /* Return: pointer to the NODE_ASN element.                       */
307 /******************************************************************/
308 asn1_node
309 _asn1_append_value (asn1_node node, const void *value, unsigned int len)
310 {
311   if (node == NULL)
312     return node;
313   if (node->value != NULL && node->value != node->small_value)
314     {
315       /* value is allocated */
316       int prev_len = node->value_len;
317       node->value_len += len;
318       node->value = realloc (node->value, node->value_len);
319       if (node->value == NULL)
320         {
321           node->value_len = 0;
322           return NULL;
323         }
324       memcpy (&node->value[prev_len], value, len);
325
326       return node;
327     }
328   else if (node->value == node->small_value)
329     {
330       /* value is in node */
331       int prev_len = node->value_len;
332       node->value_len += len;
333       node->value = malloc (node->value_len);
334       if (node->value == NULL)
335         {
336           node->value_len = 0;
337           return NULL;
338         }
339       memcpy (node->value, node->small_value, prev_len);
340       memcpy (&node->value[prev_len], value, len);
341
342       return node;
343     }
344   else                          /* node->value == NULL */
345     return _asn1_set_value (node, value, len);
346 }
347
348 /******************************************************************/
349 /* Function : _asn1_set_name                                      */
350 /* Description: sets the field NAME in a NODE_ASN element. The    */
351 /*              previous value (if exist) will be lost            */
352 /* Parameters:                                                    */
353 /*   node: element pointer.                                       */
354 /*   name: a null terminated string with the name that you want   */
355 /*         to set.                                                */
356 /* Return: pointer to the NODE_ASN element.                       */
357 /******************************************************************/
358 asn1_node
359 _asn1_set_name (asn1_node node, const char *name)
360 {
361   unsigned int nsize;
362
363   if (node == NULL)
364     return node;
365
366   if (name == NULL)
367     {
368       node->name[0] = 0;
369       node->name_hash = hash_pjw_bare (node->name, 0);
370       return node;
371     }
372
373   nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
374   node->name_hash = hash_pjw_bare (node->name, nsize);
375
376   return node;
377 }
378
379 /******************************************************************/
380 /* Function : _asn1_cpy_name                                      */
381 /* Description: copies the field NAME in a NODE_ASN element.      */
382 /* Parameters:                                                    */
383 /*   dst: a dest element pointer.                                 */
384 /*   src: a source element pointer.                               */
385 /* Return: pointer to the NODE_ASN element.                       */
386 /******************************************************************/
387 asn1_node
388 _asn1_cpy_name (asn1_node dst, asn1_node src)
389 {
390   if (dst == NULL)
391     return dst;
392
393   if (src == NULL)
394     {
395       dst->name[0] = 0;
396       dst->name_hash = hash_pjw_bare (dst->name, 0);
397       return dst;
398     }
399
400   _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
401   dst->name_hash = src->name_hash;
402
403   return dst;
404 }
405
406 /******************************************************************/
407 /* Function : _asn1_set_right                                     */
408 /* Description: sets the field RIGHT in a NODE_ASN element.       */
409 /* Parameters:                                                    */
410 /*   node: element pointer.                                       */
411 /*   right: pointer to a NODE_ASN element that you want be pointed*/
412 /*          by NODE.                                              */
413 /* Return: pointer to *NODE.                                      */
414 /******************************************************************/
415 asn1_node
416 _asn1_set_right (asn1_node node, asn1_node right)
417 {
418   if (node == NULL)
419     return node;
420   node->right = right;
421   if (right)
422     right->left = node;
423   return node;
424 }
425
426
427 /******************************************************************/
428 /* Function : _asn1_get_last_right                                */
429 /* Description: return the last element along the right chain.    */
430 /* Parameters:                                                    */
431 /*   node: starting element pointer.                              */
432 /* Return: pointer to the last element along the right chain.     */
433 /******************************************************************/
434 asn1_node
435 _asn1_get_last_right (asn1_node node)
436 {
437   asn1_node p;
438
439   if (node == NULL)
440     return NULL;
441   p = node;
442   while (p->right)
443     p = p->right;
444   return p;
445 }
446
447 /******************************************************************/
448 /* Function : _asn1_remove_node                                   */
449 /* Description: gets free the memory allocated for an NODE_ASN    */
450 /*              element (not the elements pointed by it).         */
451 /* Parameters:                                                    */
452 /*   node: NODE_ASN element pointer.                              */
453 /*   flags: ASN1_DELETE_FLAG_*                                    */
454 /******************************************************************/
455 void
456 _asn1_remove_node (asn1_node node, unsigned int flags)
457 {
458   if (node == NULL)
459     return;
460
461   if (flags & ASN1_DELETE_FLAG_ZEROIZE)
462     memset(node->value, 0, node->value_len);
463
464   if (node->value != NULL && node->value != node->small_value)
465     free (node->value);
466   free (node);
467 }
468
469 /******************************************************************/
470 /* Function : _asn1_find_up                                       */
471 /* Description: return the father of the NODE_ASN element.        */
472 /* Parameters:                                                    */
473 /*   node: NODE_ASN element pointer.                              */
474 /* Return: Null if not found.                                     */
475 /******************************************************************/
476 asn1_node
477 _asn1_find_up (asn1_node node)
478 {
479   asn1_node p;
480
481   if (node == NULL)
482     return NULL;
483
484   p = node;
485
486   while ((p->left != NULL) && (p->left->right == p))
487     p = p->left;
488
489   return p->left;
490 }
491
492 /******************************************************************/
493 /* Function : _asn1_delete_list                                   */
494 /* Description: deletes the list elements (not the elements       */
495 /*  pointed by them).                                             */
496 /******************************************************************/
497 void
498 _asn1_delete_list (void)
499 {
500   list_type *listElement;
501
502   while (firstElement)
503     {
504       listElement = firstElement;
505       firstElement = firstElement->next;
506       free (listElement);
507     }
508 }
509
510 /******************************************************************/
511 /* Function : _asn1_delete_list_and nodes                         */
512 /* Description: deletes the list elements and the elements        */
513 /*  pointed by them.                                              */
514 /******************************************************************/
515 void
516 _asn1_delete_list_and_nodes (void)
517 {
518   list_type *listElement;
519
520   while (firstElement)
521     {
522       listElement = firstElement;
523       firstElement = firstElement->next;
524       _asn1_remove_node (listElement->node, 0);
525       free (listElement);
526     }
527 }
528
529
530 char *
531 _asn1_ltostr (long v, char *str)
532 {
533   long d, r;
534   char temp[20];
535   int count, k, start;
536
537   if (v < 0)
538     {
539       str[0] = '-';
540       start = 1;
541       v = -v;
542     }
543   else
544     start = 0;
545
546   count = 0;
547   do
548     {
549       d = v / 10;
550       r = v - d * 10;
551       temp[start + count] = '0' + (char) r;
552       count++;
553       v = d;
554     }
555   while (v);
556
557   for (k = 0; k < count; k++)
558     str[k + start] = temp[start + count - k - 1];
559   str[count + start] = 0;
560   return str;
561 }
562
563
564 /******************************************************************/
565 /* Function : _asn1_change_integer_value                          */
566 /* Description: converts into DER coding the value assign to an   */
567 /*   INTEGER constant.                                            */
568 /* Parameters:                                                    */
569 /*   node: root of an ASN1element.                                */
570 /* Return:                                                        */
571 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
572 /*   otherwise ASN1_SUCCESS                                             */
573 /******************************************************************/
574 int
575 _asn1_change_integer_value (asn1_node node)
576 {
577   asn1_node p;
578   unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
579   unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
580   int len;
581
582   if (node == NULL)
583     return ASN1_ELEMENT_NOT_FOUND;
584
585   p = node;
586   while (p)
587     {
588       if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
589           && (p->type & CONST_ASSIGN))
590         {
591           if (p->value)
592             {
593               _asn1_convert_integer (p->value, val, sizeof (val), &len);
594               asn1_octet_der (val, len, val2, &len);
595               _asn1_set_value (p, val2, len);
596             }
597         }
598
599       if (p->down)
600         {
601           p = p->down;
602         }
603       else
604         {
605           if (p == node)
606             p = NULL;
607           else if (p->right)
608             p = p->right;
609           else
610             {
611               while (1)
612                 {
613                   p = _asn1_find_up (p);
614                   if (p == node)
615                     {
616                       p = NULL;
617                       break;
618                     }
619                   if (p->right)
620                     {
621                       p = p->right;
622                       break;
623                     }
624                 }
625             }
626         }
627     }
628
629   return ASN1_SUCCESS;
630 }
631
632
633 /******************************************************************/
634 /* Function : _asn1_expand_object_id                              */
635 /* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
636 /* Parameters:                                                    */
637 /*   node: root of an ASN1 element.                               */
638 /* Return:                                                        */
639 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
640 /*   otherwise ASN1_SUCCESS                                             */
641 /******************************************************************/
642 int
643 _asn1_expand_object_id (asn1_node node)
644 {
645   asn1_node p, p2, p3, p4, p5;
646   char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
647   int move, tlen;
648
649   if (node == NULL)
650     return ASN1_ELEMENT_NOT_FOUND;
651
652   _asn1_str_cpy (name_root, sizeof (name_root), node->name);
653
654   p = node;
655   move = DOWN;
656
657   while (!((p == node) && (move == UP)))
658     {
659       if (move != UP)
660         {
661           if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
662               && (p->type & CONST_ASSIGN))
663             {
664               p2 = p->down;
665               if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
666                 {
667                   if (p2->value && !isdigit (p2->value[0]))
668                     {
669                       _asn1_str_cpy (name2, sizeof (name2), name_root);
670                       _asn1_str_cat (name2, sizeof (name2), ".");
671                       _asn1_str_cat (name2, sizeof (name2),
672                                      (char *) p2->value);
673                       p3 = asn1_find_node (node, name2);
674                       if (!p3
675                           || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
676                           || !(p3->type & CONST_ASSIGN))
677                         return ASN1_ELEMENT_NOT_FOUND;
678                       _asn1_set_down (p, p2->right);
679                       _asn1_remove_node (p2, 0);
680                       p2 = p;
681                       p4 = p3->down;
682                       while (p4)
683                         {
684                           if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
685                             {
686                               p5 =
687                                 _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
688                               _asn1_set_name (p5, p4->name);
689                               tlen = _asn1_strlen (p4->value);
690                               if (tlen > 0)
691                                 _asn1_set_value (p5, p4->value, tlen + 1);
692                               if (p2 == p)
693                                 {
694                                   _asn1_set_right (p5, p->down);
695                                   _asn1_set_down (p, p5);
696                                 }
697                               else
698                                 {
699                                   _asn1_set_right (p5, p2->right);
700                                   _asn1_set_right (p2, p5);
701                                 }
702                               p2 = p5;
703                             }
704                           p4 = p4->right;
705                         }
706                       move = DOWN;
707                       continue;
708                     }
709                 }
710             }
711           move = DOWN;
712         }
713       else
714         move = RIGHT;
715
716       if (move == DOWN)
717         {
718           if (p->down)
719             p = p->down;
720           else
721             move = RIGHT;
722         }
723
724       if (p == node)
725         {
726           move = UP;
727           continue;
728         }
729
730       if (move == RIGHT)
731         {
732           if (p->right)
733             p = p->right;
734           else
735             move = UP;
736         }
737       if (move == UP)
738         p = _asn1_find_up (p);
739     }
740
741
742   /*******************************/
743   /*       expand DEFAULT        */
744   /*******************************/
745   p = node;
746   move = DOWN;
747
748   while (!((p == node) && (move == UP)))
749     {
750       if (move != UP)
751         {
752           if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
753               (p->type & CONST_DEFAULT))
754             {
755               p2 = p->down;
756               if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
757                 {
758                   _asn1_str_cpy (name2, sizeof (name2), name_root);
759                   _asn1_str_cat (name2, sizeof (name2), ".");
760                   _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
761                   p3 = asn1_find_node (node, name2);
762                   if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
763                       || !(p3->type & CONST_ASSIGN))
764                     return ASN1_ELEMENT_NOT_FOUND;
765                   p4 = p3->down;
766                   name2[0] = 0;
767                   while (p4)
768                     {
769                       if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
770                         {
771                           if (name2[0])
772                             _asn1_str_cat (name2, sizeof (name2), ".");
773                           _asn1_str_cat (name2, sizeof (name2),
774                                          (char *) p4->value);
775                         }
776                       p4 = p4->right;
777                     }
778                   tlen = strlen (name2);
779                   if (tlen > 0)
780                     _asn1_set_value (p2, name2, tlen + 1);
781                 }
782             }
783           move = DOWN;
784         }
785       else
786         move = RIGHT;
787
788       if (move == DOWN)
789         {
790           if (p->down)
791             p = p->down;
792           else
793             move = RIGHT;
794         }
795
796       if (p == node)
797         {
798           move = UP;
799           continue;
800         }
801
802       if (move == RIGHT)
803         {
804           if (p->right)
805             p = p->right;
806           else
807             move = UP;
808         }
809       if (move == UP)
810         p = _asn1_find_up (p);
811     }
812
813   return ASN1_SUCCESS;
814 }
815
816
817 /******************************************************************/
818 /* Function : _asn1_type_set_config                               */
819 /* Description: sets the CONST_SET and CONST_NOT_USED properties  */
820 /*   in the fields of the SET elements.                           */
821 /* Parameters:                                                    */
822 /*   node: root of an ASN1 element.                               */
823 /* Return:                                                        */
824 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
825 /*   otherwise ASN1_SUCCESS                                             */
826 /******************************************************************/
827 int
828 _asn1_type_set_config (asn1_node node)
829 {
830   asn1_node p, p2;
831   int move;
832
833   if (node == NULL)
834     return ASN1_ELEMENT_NOT_FOUND;
835
836   p = node;
837   move = DOWN;
838
839   while (!((p == node) && (move == UP)))
840     {
841       if (move != UP)
842         {
843           if (type_field (p->type) == ASN1_ETYPE_SET)
844             {
845               p2 = p->down;
846               while (p2)
847                 {
848                   if (type_field (p2->type) != ASN1_ETYPE_TAG)
849                     p2->type |= CONST_SET | CONST_NOT_USED;
850                   p2 = p2->right;
851                 }
852             }
853           move = DOWN;
854         }
855       else
856         move = RIGHT;
857
858       if (move == DOWN)
859         {
860           if (p->down)
861             p = p->down;
862           else
863             move = RIGHT;
864         }
865
866       if (p == node)
867         {
868           move = UP;
869           continue;
870         }
871
872       if (move == RIGHT)
873         {
874           if (p->right)
875             p = p->right;
876           else
877             move = UP;
878         }
879       if (move == UP)
880         p = _asn1_find_up (p);
881     }
882
883   return ASN1_SUCCESS;
884 }
885
886
887 /******************************************************************/
888 /* Function : _asn1_check_identifier                              */
889 /* Description: checks the definitions of all the identifiers     */
890 /*   and the first element of an OBJECT_ID (e.g. {pkix 0 4}).     */
891 /*   The _asn1_identifierMissing global variable is filled if     */
892 /*   necessary.                                                   */
893 /* Parameters:                                                    */
894 /*   node: root of an ASN1 element.                               */
895 /* Return:                                                        */
896 /*   ASN1_ELEMENT_NOT_FOUND      if NODE is NULL,                 */
897 /*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
898 /*   otherwise ASN1_SUCCESS                                       */
899 /******************************************************************/
900 int
901 _asn1_check_identifier (asn1_node node)
902 {
903   asn1_node p, p2;
904   char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
905
906   if (node == NULL)
907     return ASN1_ELEMENT_NOT_FOUND;
908
909   p = node;
910   while (p)
911     {
912       if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
913         {
914           _asn1_str_cpy (name2, sizeof (name2), node->name);
915           _asn1_str_cat (name2, sizeof (name2), ".");
916           _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
917           p2 = asn1_find_node (node, name2);
918           if (p2 == NULL)
919             {
920               if (p->value)
921                 _asn1_strcpy (_asn1_identifierMissing, p->value);
922               else
923                 _asn1_strcpy (_asn1_identifierMissing, "(null)");
924               return ASN1_IDENTIFIER_NOT_FOUND;
925             }
926         }
927       else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
928                (p->type & CONST_DEFAULT))
929         {
930           p2 = p->down;
931           if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
932             {
933               _asn1_str_cpy (name2, sizeof (name2), node->name);
934               _asn1_str_cat (name2, sizeof (name2), ".");
935               _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
936               _asn1_strcpy (_asn1_identifierMissing, p2->value);
937               p2 = asn1_find_node (node, name2);
938               if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
939                   !(p2->type & CONST_ASSIGN))
940                 return ASN1_IDENTIFIER_NOT_FOUND;
941               else
942                 _asn1_identifierMissing[0] = 0;
943             }
944         }
945       else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
946                (p->type & CONST_ASSIGN))
947         {
948           p2 = p->down;
949           if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
950             {
951               if (p2->value && !isdigit (p2->value[0]))
952                 {
953                   _asn1_str_cpy (name2, sizeof (name2), node->name);
954                   _asn1_str_cat (name2, sizeof (name2), ".");
955                   _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
956                   _asn1_strcpy (_asn1_identifierMissing, p2->value);
957                   p2 = asn1_find_node (node, name2);
958                   if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
959                       || !(p2->type & CONST_ASSIGN))
960                     return ASN1_IDENTIFIER_NOT_FOUND;
961                   else
962                     _asn1_identifierMissing[0] = 0;
963                 }
964             }
965         }
966
967       if (p->down)
968         {
969           p = p->down;
970         }
971       else if (p->right)
972         p = p->right;
973       else
974         {
975           while (1)
976             {
977               p = _asn1_find_up (p);
978               if (p == node)
979                 {
980                   p = NULL;
981                   break;
982                 }
983               if (p->right)
984                 {
985                   p = p->right;
986                   break;
987                 }
988             }
989         }
990     }
991
992   return ASN1_SUCCESS;
993 }
994
995
996 /******************************************************************/
997 /* Function : _asn1_set_default_tag                               */
998 /* Description: sets the default IMPLICIT or EXPLICIT property in */
999 /*   the tagged elements that don't have this declaration.        */
1000 /* Parameters:                                                    */
1001 /*   node: pointer to a DEFINITIONS element.                      */
1002 /* Return:                                                        */
1003 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to   */
1004 /*     a DEFINITIONS element,                                     */
1005 /*   otherwise ASN1_SUCCESS                                       */
1006 /******************************************************************/
1007 int
1008 _asn1_set_default_tag (asn1_node node)
1009 {
1010   asn1_node p;
1011
1012   if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
1013     return ASN1_ELEMENT_NOT_FOUND;
1014
1015   p = node;
1016   while (p)
1017     {
1018       if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
1019           !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1020         {
1021           if (node->type & CONST_EXPLICIT)
1022             p->type |= CONST_EXPLICIT;
1023           else
1024             p->type |= CONST_IMPLICIT;
1025         }
1026
1027       if (p->down)
1028         {
1029           p = p->down;
1030         }
1031       else if (p->right)
1032         p = p->right;
1033       else
1034         {
1035           while (1)
1036             {
1037               p = _asn1_find_up (p);
1038               if (p == node)
1039                 {
1040                   p = NULL;
1041                   break;
1042                 }
1043               if (p->right)
1044                 {
1045                   p = p->right;
1046                   break;
1047                 }
1048             }
1049         }
1050     }
1051
1052   return ASN1_SUCCESS;
1053 }