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