~ubuntu-branches/ubuntu/lucid/libtasn1-3/lucid-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2015-2806.patch/lib/parser_aux.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-04-02 11:27:53 UTC
  • Revision ID: package-import@ubuntu.com-20150402112753-ek5d5e0lzmg7r3mr
Tags: 2.4-1ubuntu0.3
* SECURITY UPDATE: denial of service and possible code execution via
  overflow in _asn1_ltostr
  - debian/patches/CVE-2015-2806.patch: introduce LTOSTR_MAX_SIZE and use
    in lib/coding.c, lib/decoding.c, lib/element.c, lib/parser_aux.c,
    lib/parser_aux.h.
  - CVE-2015-2806

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010 Free
 
3
 * Software Foundation, Inc.
 
4
 *
 
5
 * This file is part of LIBTASN1.
 
6
 *
 
7
 * The LIBTASN1 library is free software; you can redistribute it
 
8
 * and/or modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
20
 * 02110-1301, USA
 
21
 */
 
22
 
 
23
#include <int.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_TYPE 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_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 TYPE_         */
 
52
/*         and CONST_ constants).                     */
 
53
/* Return: pointer to the new element.                */
 
54
/******************************************************/
 
55
ASN1_TYPE
 
56
_asn1_add_node (unsigned int type)
 
57
{
 
58
  list_type *listElement;
 
59
  ASN1_TYPE punt;
 
60
 
 
61
  punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
 
62
  if (punt == NULL)
 
63
    return NULL;
 
64
 
 
65
  listElement = (list_type *) _asn1_malloc (sizeof (list_type));
 
66
  if (listElement == NULL)
 
67
    {
 
68
      _asn1_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
 * Return value: the searching result. NULL if not found.
 
92
 **/
 
93
ASN1_TYPE
 
94
asn1_find_node (ASN1_TYPE pointer, const char *name)
 
95
{
 
96
  ASN1_TYPE p;
 
97
  char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
 
98
  const char *n_start;
 
99
 
 
100
  if (pointer == NULL)
 
101
    return NULL;
 
102
 
 
103
  if (name == NULL)
 
104
    return NULL;
 
105
 
 
106
  p = pointer;
 
107
  n_start = name;
 
108
 
 
109
  if (p->name != NULL)
 
110
    {                           /* has *pointer got a name ? */
 
111
      n_end = strchr (n_start, '.');    /* search the first dot */
 
112
      if (n_end)
 
113
        {
 
114
          memcpy (n, n_start, n_end - n_start);
 
115
          n[n_end - n_start] = 0;
 
116
          n_start = n_end;
 
117
          n_start++;
 
118
        }
 
119
      else
 
120
        {
 
121
          _asn1_str_cpy (n, sizeof (n), n_start);
 
122
          n_start = NULL;
 
123
        }
 
124
 
 
125
      while (p)
 
126
        {
 
127
          if ((p->name) && (!strcmp (p->name, n)))
 
128
            break;
 
129
          else
 
130
            p = p->right;
 
131
        }                       /* while */
 
132
 
 
133
      if (p == NULL)
 
134
        return NULL;
 
135
    }
 
136
  else
 
137
    {                           /* *pointer doesn't have a name */
 
138
      if (n_start[0] == 0)
 
139
        return p;
 
140
    }
 
141
 
 
142
  while (n_start)
 
143
    {                           /* Has the end of NAME been reached? */
 
144
      n_end = strchr (n_start, '.');    /* search the next dot */
 
145
      if (n_end)
 
146
        {
 
147
          memcpy (n, n_start, n_end - n_start);
 
148
          n[n_end - n_start] = 0;
 
149
          n_start = n_end;
 
150
          n_start++;
 
151
        }
 
152
      else
 
153
        {
 
154
          _asn1_str_cpy (n, sizeof (n), n_start);
 
155
          n_start = NULL;
 
156
        }
 
157
 
 
158
      if (p->down == NULL)
 
159
        return NULL;
 
160
 
 
161
      p = p->down;
 
162
 
 
163
      /* The identifier "?LAST" indicates the last element 
 
164
         in the right chain. */
 
165
      if (!strcmp (n, "?LAST"))
 
166
        {
 
167
          if (p == NULL)
 
168
            return NULL;
 
169
          while (p->right)
 
170
            p = p->right;
 
171
        }
 
172
      else
 
173
        {                       /* no "?LAST" */
 
174
          while (p)
 
175
            {
 
176
              if ((p->name) && (!strcmp (p->name, n)))
 
177
                break;
 
178
              else
 
179
                p = p->right;
 
180
            }
 
181
          if (p == NULL)
 
182
            return NULL;
 
183
        }
 
184
    }                           /* while */
 
185
 
 
186
  return p;
 
187
}
 
188
 
 
189
 
 
190
/******************************************************************/
 
191
/* Function : _asn1_set_value                                     */
 
192
/* Description: sets the field VALUE in a NODE_ASN element. The   */
 
193
/*              previous value (if exist) will be lost            */
 
194
/* Parameters:                                                    */
 
195
/*   node: element pointer.                                       */
 
196
/*   value: pointer to the value that you want to set.            */
 
197
/*   len: character number of value.                              */
 
198
/* Return: pointer to the NODE_ASN element.                       */
 
199
/******************************************************************/
 
200
ASN1_TYPE
 
201
_asn1_set_value (ASN1_TYPE node, const void *value, unsigned int len)
 
202
{
 
203
  if (node == NULL)
 
204
    return node;
 
205
  if (node->value)
 
206
    {
 
207
      if (node->value != node->small_value)
 
208
        _asn1_free (node->value);
 
209
      node->value = NULL;
 
210
      node->value_len = 0;
 
211
    }
 
212
 
 
213
  if (!len)
 
214
    return node;
 
215
 
 
216
  if (len < sizeof (node->small_value))
 
217
    {
 
218
      node->value = node->small_value;
 
219
    }
 
220
  else
 
221
    {
 
222
      node->value = _asn1_malloc (len);
 
223
      if (node->value == NULL)
 
224
        return NULL;
 
225
    }
 
226
  node->value_len = len;
 
227
 
 
228
  memcpy (node->value, value, len);
 
229
  return node;
 
230
}
 
231
 
 
232
/******************************************************************/
 
233
/* Function : _asn1_set_value_octet                               */
 
234
/* Description: sets the field VALUE in a NODE_ASN element. The   */
 
235
/*              previous value (if exist) will be lost. The value */
 
236
/*              given is stored as an octet string.               */
 
237
/* Parameters:                                                    */
 
238
/*   node: element pointer.                                       */
 
239
/*   value: pointer to the value that you want to set.            */
 
240
/*   len: character number of value.                              */
 
241
/* Return: pointer to the NODE_ASN element.                       */
 
242
/******************************************************************/
 
243
ASN1_TYPE
 
244
_asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len)
 
245
{
 
246
  int len2;
 
247
  void *temp;
 
248
 
 
249
  if (node == NULL)
 
250
    return node;
 
251
 
 
252
  asn1_length_der (len, NULL, &len2);
 
253
  temp = (unsigned char *) _asn1_malloc (len + len2);
 
254
  if (temp == NULL)
 
255
    return NULL;
 
256
 
 
257
  asn1_octet_der (value, len, temp, &len2);
 
258
  return _asn1_set_value_m (node, temp, len2);
 
259
}
 
260
 
 
261
/* the same as _asn1_set_value except that it sets an already malloc'ed
 
262
 * value.
 
263
 */
 
264
ASN1_TYPE
 
265
_asn1_set_value_m (ASN1_TYPE node, void *value, unsigned int len)
 
266
{
 
267
  if (node == NULL)
 
268
    return node;
 
269
 
 
270
  if (node->value)
 
271
    {
 
272
      if (node->value != node->small_value)
 
273
        _asn1_free (node->value);
 
274
      node->value = NULL;
 
275
      node->value_len = 0;
 
276
    }
 
277
 
 
278
  if (!len)
 
279
    return node;
 
280
 
 
281
  node->value = value;
 
282
  node->value_len = len;
 
283
 
 
284
  return node;
 
285
}
 
286
 
 
287
/******************************************************************/
 
288
/* Function : _asn1_append_value                                  */
 
289
/* Description: appends to the field VALUE in a NODE_ASN element. */
 
290
/*                                                                */
 
291
/* Parameters:                                                    */
 
292
/*   node: element pointer.                                       */
 
293
/*   value: pointer to the value that you want to be appended.    */
 
294
/*   len: character number of value.                              */
 
295
/* Return: pointer to the NODE_ASN element.                       */
 
296
/******************************************************************/
 
297
ASN1_TYPE
 
298
_asn1_append_value (ASN1_TYPE node, const void *value, unsigned int len)
 
299
{
 
300
  if (node == NULL)
 
301
    return node;
 
302
  if (node->value != NULL && node->value != node->small_value)
 
303
    {
 
304
      /* value is allocated */
 
305
      int prev_len = node->value_len;
 
306
      node->value_len += len;
 
307
      node->value = _asn1_realloc (node->value, node->value_len);
 
308
      if (node->value == NULL)
 
309
        {
 
310
          node->value_len = 0;
 
311
          return NULL;
 
312
        }
 
313
      memcpy (&node->value[prev_len], value, len);
 
314
 
 
315
      return node;
 
316
    }
 
317
  else if (node->value == node->small_value)
 
318
    {
 
319
      /* value is in node */
 
320
      int prev_len = node->value_len;
 
321
      node->value_len += len;
 
322
      node->value = _asn1_malloc (node->value_len);
 
323
      if (node->value == NULL)
 
324
        {
 
325
          node->value_len = 0;
 
326
          return NULL;
 
327
        }
 
328
      memcpy (node->value, node->small_value, prev_len);
 
329
      memcpy (&node->value[prev_len], value, len);
 
330
 
 
331
      return node;
 
332
    }
 
333
  else                          /* node->value == NULL */
 
334
    return _asn1_set_value (node, value, len);
 
335
}
 
336
 
 
337
/******************************************************************/
 
338
/* Function : _asn1_set_name                                      */
 
339
/* Description: sets the field NAME in a NODE_ASN element. The    */
 
340
/*              previous value (if exist) will be lost            */
 
341
/* Parameters:                                                    */
 
342
/*   node: element pointer.                                       */
 
343
/*   name: a null terminated string with the name that you want   */
 
344
/*         to set.                                                */
 
345
/* Return: pointer to the NODE_ASN element.                       */
 
346
/******************************************************************/
 
347
ASN1_TYPE
 
348
_asn1_set_name (ASN1_TYPE node, const char *name)
 
349
{
 
350
  if (node == NULL)
 
351
    return node;
 
352
 
 
353
  if (node->name)
 
354
    {
 
355
      _asn1_free (node->name);
 
356
      node->name = NULL;
 
357
    }
 
358
 
 
359
  if (name == NULL)
 
360
    return node;
 
361
 
 
362
  if (strlen (name))
 
363
    {
 
364
      node->name = (char *) _asn1_strdup (name);
 
365
      if (node->name == NULL)
 
366
        return NULL;
 
367
    }
 
368
  else
 
369
    node->name = NULL;
 
370
  return node;
 
371
}
 
372
 
 
373
/******************************************************************/
 
374
/* Function : _asn1_set_right                                     */
 
375
/* Description: sets the field RIGHT in a NODE_ASN element.       */
 
376
/* Parameters:                                                    */
 
377
/*   node: element pointer.                                       */
 
378
/*   right: pointer to a NODE_ASN element that you want be pointed*/
 
379
/*          by NODE.                                              */
 
380
/* Return: pointer to *NODE.                                      */
 
381
/******************************************************************/
 
382
ASN1_TYPE
 
383
_asn1_set_right (ASN1_TYPE node, ASN1_TYPE right)
 
384
{
 
385
  if (node == NULL)
 
386
    return node;
 
387
  node->right = right;
 
388
  if (right)
 
389
    right->left = node;
 
390
  return node;
 
391
}
 
392
 
 
393
/******************************************************************/
 
394
/* Function : _asn1_get_right                                     */
 
395
/* Description: returns the element pointed by the RIGHT field of */
 
396
/*              a NODE_ASN element.                               */
 
397
/* Parameters:                                                    */
 
398
/*   node: NODE_ASN element pointer.                              */
 
399
/* Return: field RIGHT of NODE.                                   */
 
400
/******************************************************************/
 
401
ASN1_TYPE
 
402
_asn1_get_right (ASN1_TYPE node)
 
403
{
 
404
  if (node == NULL)
 
405
    return NULL;
 
406
  return node->right;
 
407
}
 
408
 
 
409
/******************************************************************/
 
410
/* Function : _asn1_get_last_right                                */
 
411
/* Description: return the last element along the right chain.    */
 
412
/* Parameters:                                                    */
 
413
/*   node: starting element pointer.                              */
 
414
/* Return: pointer to the last element along the right chain.     */
 
415
/******************************************************************/
 
416
ASN1_TYPE
 
417
_asn1_get_last_right (ASN1_TYPE node)
 
418
{
 
419
  ASN1_TYPE p;
 
420
 
 
421
  if (node == NULL)
 
422
    return NULL;
 
423
  p = node;
 
424
  while (p->right)
 
425
    p = p->right;
 
426
  return p;
 
427
}
 
428
 
 
429
/******************************************************************/
 
430
/* Function : _asn1_set_down                                      */
 
431
/* Description: sets the field DOWN in a NODE_ASN element.        */
 
432
/* Parameters:                                                    */
 
433
/*   node: element pointer.                                       */
 
434
/*   down: pointer to a NODE_ASN element that you want be pointed */
 
435
/*          by NODE.                                              */
 
436
/* Return: pointer to *NODE.                                      */
 
437
/******************************************************************/
 
438
ASN1_TYPE
 
439
_asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
 
440
{
 
441
  if (node == NULL)
 
442
    return node;
 
443
  node->down = down;
 
444
  if (down)
 
445
    down->left = node;
 
446
  return node;
 
447
}
 
448
 
 
449
/******************************************************************/
 
450
/* Function : _asn1_get_down                                      */
 
451
/* Description: returns the element pointed by the DOWN field of  */
 
452
/*              a NODE_ASN element.                               */
 
453
/* Parameters:                                                    */
 
454
/*   node: NODE_ASN element pointer.                              */
 
455
/* Return: field DOWN of NODE.                                    */
 
456
/******************************************************************/
 
457
ASN1_TYPE
 
458
_asn1_get_down (ASN1_TYPE node)
 
459
{
 
460
  if (node == NULL)
 
461
    return NULL;
 
462
  return node->down;
 
463
}
 
464
 
 
465
/******************************************************************/
 
466
/* Function : _asn1_get_name                                      */
 
467
/* Description: returns the name of a NODE_ASN element.           */
 
468
/* Parameters:                                                    */
 
469
/*   node: NODE_ASN element pointer.                              */
 
470
/* Return: a null terminated string.                              */
 
471
/******************************************************************/
 
472
char *
 
473
_asn1_get_name (ASN1_TYPE node)
 
474
{
 
475
  if (node == NULL)
 
476
    return NULL;
 
477
  return node->name;
 
478
}
 
479
 
 
480
/******************************************************************/
 
481
/* Function : _asn1_mod_type                                      */
 
482
/* Description: change the field TYPE of an NODE_ASN element.     */
 
483
/*              The new value is the old one | (bitwise or) the   */
 
484
/*              paramener VALUE.                                  */
 
485
/* Parameters:                                                    */
 
486
/*   node: NODE_ASN element pointer.                              */
 
487
/*   value: the integer value that must be or-ed with the current */
 
488
/*          value of field TYPE.                                  */
 
489
/* Return: NODE pointer.                                          */
 
490
/******************************************************************/
 
491
ASN1_TYPE
 
492
_asn1_mod_type (ASN1_TYPE node, unsigned int value)
 
493
{
 
494
  if (node == NULL)
 
495
    return node;
 
496
  node->type |= value;
 
497
  return node;
 
498
}
 
499
 
 
500
 
 
501
/******************************************************************/
 
502
/* Function : _asn1_remove_node                                   */
 
503
/* Description: gets free the memory allocated for an NODE_ASN    */
 
504
/*              element (not the elements pointed by it).         */
 
505
/* Parameters:                                                    */
 
506
/*   node: NODE_ASN element pointer.                              */
 
507
/******************************************************************/
 
508
void
 
509
_asn1_remove_node (ASN1_TYPE node)
 
510
{
 
511
  if (node == NULL)
 
512
    return;
 
513
 
 
514
  if (node->name != NULL)
 
515
    _asn1_free (node->name);
 
516
  if (node->value != NULL && node->value != node->small_value)
 
517
    _asn1_free (node->value);
 
518
  _asn1_free (node);
 
519
}
 
520
 
 
521
/******************************************************************/
 
522
/* Function : _asn1_find_up                                       */
 
523
/* Description: return the father of the NODE_ASN element.        */
 
524
/* Parameters:                                                    */
 
525
/*   node: NODE_ASN element pointer.                              */
 
526
/* Return: Null if not found.                                     */
 
527
/******************************************************************/
 
528
ASN1_TYPE
 
529
_asn1_find_up (ASN1_TYPE node)
 
530
{
 
531
  ASN1_TYPE p;
 
532
 
 
533
  if (node == NULL)
 
534
    return NULL;
 
535
 
 
536
  p = node;
 
537
 
 
538
  while ((p->left != NULL) && (p->left->right == p))
 
539
    p = p->left;
 
540
 
 
541
  return p->left;
 
542
}
 
543
 
 
544
/******************************************************************/
 
545
/* Function : _asn1_delete_list                                   */
 
546
/* Description: deletes the list elements (not the elements       */
 
547
/*  pointed by them).                                             */
 
548
/******************************************************************/
 
549
void
 
550
_asn1_delete_list (void)
 
551
{
 
552
  list_type *listElement;
 
553
 
 
554
  while (firstElement)
 
555
    {
 
556
      listElement = firstElement;
 
557
      firstElement = firstElement->next;
 
558
      _asn1_free (listElement);
 
559
    }
 
560
}
 
561
 
 
562
/******************************************************************/
 
563
/* Function : _asn1_delete_list_and nodes                         */
 
564
/* Description: deletes the list elements and the elements        */
 
565
/*  pointed by them.                                              */
 
566
/******************************************************************/
 
567
void
 
568
_asn1_delete_list_and_nodes (void)
 
569
{
 
570
  list_type *listElement;
 
571
 
 
572
  while (firstElement)
 
573
    {
 
574
      listElement = firstElement;
 
575
      firstElement = firstElement->next;
 
576
      _asn1_remove_node (listElement->node);
 
577
      _asn1_free (listElement);
 
578
    }
 
579
}
 
580
 
 
581
 
 
582
char *
 
583
_asn1_ltostr (long v, char *str)
 
584
{
 
585
  long d, r;
 
586
  char temp[20];
 
587
  int count, k, start;
 
588
 
 
589
  if (v < 0)
 
590
    {
 
591
      str[0] = '-';
 
592
      start = 1;
 
593
      v = -v;
 
594
    }
 
595
  else
 
596
    start = 0;
 
597
 
 
598
  count = 0;
 
599
  do
 
600
    {
 
601
      d = v / 10;
 
602
      r = v - d * 10;
 
603
      temp[start + count] = '0' + (char) r;
 
604
      count++;
 
605
      v = d;
 
606
    }
 
607
  while (v);
 
608
 
 
609
  for (k = 0; k < count; k++)
 
610
    str[k + start] = temp[start + count - k - 1];
 
611
  str[count + start] = 0;
 
612
  return str;
 
613
}
 
614
 
 
615
 
 
616
/******************************************************************/
 
617
/* Function : _asn1_change_integer_value                          */
 
618
/* Description: converts into DER coding the value assign to an   */
 
619
/*   INTEGER constant.                                            */
 
620
/* Parameters:                                                    */
 
621
/*   node: root of an ASN1element.                                */
 
622
/* Return:                                                        */
 
623
/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
 
624
/*   otherwise ASN1_SUCCESS                                             */
 
625
/******************************************************************/
 
626
asn1_retCode
 
627
_asn1_change_integer_value (ASN1_TYPE node)
 
628
{
 
629
  ASN1_TYPE p;
 
630
  unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
 
631
  unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
 
632
  int len;
 
633
 
 
634
  if (node == NULL)
 
635
    return ASN1_ELEMENT_NOT_FOUND;
 
636
 
 
637
  p = node;
 
638
  while (p)
 
639
    {
 
640
      if ((type_field (p->type) == TYPE_INTEGER) && (p->type & CONST_ASSIGN))
 
641
        {
 
642
          if (p->value)
 
643
            {
 
644
              _asn1_convert_integer (p->value, val, sizeof (val), &len);
 
645
              asn1_octet_der (val, len, val2, &len);
 
646
              _asn1_set_value (p, val2, len);
 
647
            }
 
648
        }
 
649
 
 
650
      if (p->down)
 
651
        {
 
652
          p = p->down;
 
653
        }
 
654
      else
 
655
        {
 
656
          if (p == node)
 
657
            p = NULL;
 
658
          else if (p->right)
 
659
            p = p->right;
 
660
          else
 
661
            {
 
662
              while (1)
 
663
                {
 
664
                  p = _asn1_find_up (p);
 
665
                  if (p == node)
 
666
                    {
 
667
                      p = NULL;
 
668
                      break;
 
669
                    }
 
670
                  if (p->right)
 
671
                    {
 
672
                      p = p->right;
 
673
                      break;
 
674
                    }
 
675
                }
 
676
            }
 
677
        }
 
678
    }
 
679
 
 
680
  return ASN1_SUCCESS;
 
681
}
 
682
 
 
683
 
 
684
/******************************************************************/
 
685
/* Function : _asn1_expand_object_id                              */
 
686
/* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
 
687
/* Parameters:                                                    */
 
688
/*   node: root of an ASN1 element.                               */
 
689
/* Return:                                                        */
 
690
/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
 
691
/*   otherwise ASN1_SUCCESS                                             */
 
692
/******************************************************************/
 
693
asn1_retCode
 
694
_asn1_expand_object_id (ASN1_TYPE node)
 
695
{
 
696
  ASN1_TYPE p, p2, p3, p4, p5;
 
697
  char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
 
698
  int move, tlen;
 
699
 
 
700
  if (node == NULL)
 
701
    return ASN1_ELEMENT_NOT_FOUND;
 
702
 
 
703
  _asn1_str_cpy (name_root, sizeof (name_root), node->name);
 
704
 
 
705
  p = node;
 
706
  move = DOWN;
 
707
 
 
708
  while (!((p == node) && (move == UP)))
 
709
    {
 
710
      if (move != UP)
 
711
        {
 
712
          if ((type_field (p->type) == TYPE_OBJECT_ID)
 
713
              && (p->type & CONST_ASSIGN))
 
714
            {
 
715
              p2 = p->down;
 
716
              if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
 
717
                {
 
718
                  if (p2->value && !isdigit (p2->value[0]))
 
719
                    {
 
720
                      _asn1_str_cpy (name2, sizeof (name2), name_root);
 
721
                      _asn1_str_cat (name2, sizeof (name2), ".");
 
722
                      _asn1_str_cat (name2, sizeof (name2), p2->value);
 
723
                      p3 = asn1_find_node (node, name2);
 
724
                      if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
 
725
                          !(p3->type & CONST_ASSIGN))
 
726
                        return ASN1_ELEMENT_NOT_FOUND;
 
727
                      _asn1_set_down (p, p2->right);
 
728
                      _asn1_remove_node (p2);
 
729
                      p2 = p;
 
730
                      p4 = p3->down;
 
731
                      while (p4)
 
732
                        {
 
733
                          if (type_field (p4->type) == TYPE_CONSTANT)
 
734
                            {
 
735
                              p5 = _asn1_add_node_only (TYPE_CONSTANT);
 
736
                              _asn1_set_name (p5, p4->name);
 
737
                              tlen = strlen (p4->value);
 
738
                              if (tlen > 0)
 
739
                                _asn1_set_value (p5, p4->value, tlen + 1);
 
740
                              if (p2 == p)
 
741
                                {
 
742
                                  _asn1_set_right (p5, p->down);
 
743
                                  _asn1_set_down (p, p5);
 
744
                                }
 
745
                              else
 
746
                                {
 
747
                                  _asn1_set_right (p5, p2->right);
 
748
                                  _asn1_set_right (p2, p5);
 
749
                                }
 
750
                              p2 = p5;
 
751
                            }
 
752
                          p4 = p4->right;
 
753
                        }
 
754
                      move = DOWN;
 
755
                      continue;
 
756
                    }
 
757
                }
 
758
            }
 
759
          move = DOWN;
 
760
        }
 
761
      else
 
762
        move = RIGHT;
 
763
 
 
764
      if (move == DOWN)
 
765
        {
 
766
          if (p->down)
 
767
            p = p->down;
 
768
          else
 
769
            move = RIGHT;
 
770
        }
 
771
 
 
772
      if (p == node)
 
773
        {
 
774
          move = UP;
 
775
          continue;
 
776
        }
 
777
 
 
778
      if (move == RIGHT)
 
779
        {
 
780
          if (p->right)
 
781
            p = p->right;
 
782
          else
 
783
            move = UP;
 
784
        }
 
785
      if (move == UP)
 
786
        p = _asn1_find_up (p);
 
787
    }
 
788
 
 
789
 
 
790
  /*******************************/
 
791
  /*       expand DEFAULT        */
 
792
  /*******************************/
 
793
  p = node;
 
794
  move = DOWN;
 
795
 
 
796
  while (!((p == node) && (move == UP)))
 
797
    {
 
798
      if (move != UP)
 
799
        {
 
800
          if ((type_field (p->type) == TYPE_OBJECT_ID) &&
 
801
              (p->type & CONST_DEFAULT))
 
802
            {
 
803
              p2 = p->down;
 
804
              if (p2 && (type_field (p2->type) == TYPE_DEFAULT))
 
805
                {
 
806
                  _asn1_str_cpy (name2, sizeof (name2), name_root);
 
807
                  _asn1_str_cat (name2, sizeof (name2), ".");
 
808
                  _asn1_str_cat (name2, sizeof (name2), p2->value);
 
809
                  p3 = asn1_find_node (node, name2);
 
810
                  if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
 
811
                      !(p3->type & CONST_ASSIGN))
 
812
                    return ASN1_ELEMENT_NOT_FOUND;
 
813
                  p4 = p3->down;
 
814
                  name2[0] = 0;
 
815
                  while (p4)
 
816
                    {
 
817
                      if (type_field (p4->type) == TYPE_CONSTANT)
 
818
                        {
 
819
                          if (name2[0])
 
820
                            _asn1_str_cat (name2, sizeof (name2), ".");
 
821
                          _asn1_str_cat (name2, sizeof (name2), p4->value);
 
822
                        }
 
823
                      p4 = p4->right;
 
824
                    }
 
825
                  tlen = strlen (name2);
 
826
                  if (tlen > 0)
 
827
                    _asn1_set_value (p2, name2, tlen + 1);
 
828
                }
 
829
            }
 
830
          move = DOWN;
 
831
        }
 
832
      else
 
833
        move = RIGHT;
 
834
 
 
835
      if (move == DOWN)
 
836
        {
 
837
          if (p->down)
 
838
            p = p->down;
 
839
          else
 
840
            move = RIGHT;
 
841
        }
 
842
 
 
843
      if (p == node)
 
844
        {
 
845
          move = UP;
 
846
          continue;
 
847
        }
 
848
 
 
849
      if (move == RIGHT)
 
850
        {
 
851
          if (p->right)
 
852
            p = p->right;
 
853
          else
 
854
            move = UP;
 
855
        }
 
856
      if (move == UP)
 
857
        p = _asn1_find_up (p);
 
858
    }
 
859
 
 
860
  return ASN1_SUCCESS;
 
861
}
 
862
 
 
863
 
 
864
/******************************************************************/
 
865
/* Function : _asn1_type_set_config                               */
 
866
/* Description: sets the CONST_SET and CONST_NOT_USED properties  */
 
867
/*   in the fields of the SET elements.                           */
 
868
/* Parameters:                                                    */
 
869
/*   node: root of an ASN1 element.                               */
 
870
/* Return:                                                        */
 
871
/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
 
872
/*   otherwise ASN1_SUCCESS                                             */
 
873
/******************************************************************/
 
874
asn1_retCode
 
875
_asn1_type_set_config (ASN1_TYPE node)
 
876
{
 
877
  ASN1_TYPE p, p2;
 
878
  int move;
 
879
 
 
880
  if (node == NULL)
 
881
    return ASN1_ELEMENT_NOT_FOUND;
 
882
 
 
883
  p = node;
 
884
  move = DOWN;
 
885
 
 
886
  while (!((p == node) && (move == UP)))
 
887
    {
 
888
      if (move != UP)
 
889
        {
 
890
          if (type_field (p->type) == TYPE_SET)
 
891
            {
 
892
              p2 = p->down;
 
893
              while (p2)
 
894
                {
 
895
                  if (type_field (p2->type) != TYPE_TAG)
 
896
                    p2->type |= CONST_SET | CONST_NOT_USED;
 
897
                  p2 = p2->right;
 
898
                }
 
899
            }
 
900
          move = DOWN;
 
901
        }
 
902
      else
 
903
        move = RIGHT;
 
904
 
 
905
      if (move == DOWN)
 
906
        {
 
907
          if (p->down)
 
908
            p = p->down;
 
909
          else
 
910
            move = RIGHT;
 
911
        }
 
912
 
 
913
      if (p == node)
 
914
        {
 
915
          move = UP;
 
916
          continue;
 
917
        }
 
918
 
 
919
      if (move == RIGHT)
 
920
        {
 
921
          if (p->right)
 
922
            p = p->right;
 
923
          else
 
924
            move = UP;
 
925
        }
 
926
      if (move == UP)
 
927
        p = _asn1_find_up (p);
 
928
    }
 
929
 
 
930
  return ASN1_SUCCESS;
 
931
}
 
932
 
 
933
 
 
934
/******************************************************************/
 
935
/* Function : _asn1_check_identifier                              */
 
936
/* Description: checks the definitions of all the identifiers     */
 
937
/*   and the first element of an OBJECT_ID (e.g. {pkix 0 4}).     */
 
938
/*   The _asn1_identifierMissing global variable is filled if     */
 
939
/*   necessary.                                                   */
 
940
/* Parameters:                                                    */
 
941
/*   node: root of an ASN1 element.                               */
 
942
/* Return:                                                        */
 
943
/*   ASN1_ELEMENT_NOT_FOUND      if NODE is NULL,                 */
 
944
/*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
 
945
/*   otherwise ASN1_SUCCESS                                       */
 
946
/******************************************************************/
 
947
asn1_retCode
 
948
_asn1_check_identifier (ASN1_TYPE node)
 
949
{
 
950
  ASN1_TYPE p, p2;
 
951
  char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
 
952
 
 
953
  if (node == NULL)
 
954
    return ASN1_ELEMENT_NOT_FOUND;
 
955
 
 
956
  p = node;
 
957
  while (p)
 
958
    {
 
959
      if (type_field (p->type) == TYPE_IDENTIFIER)
 
960
        {
 
961
          _asn1_str_cpy (name2, sizeof (name2), node->name);
 
962
          _asn1_str_cat (name2, sizeof (name2), ".");
 
963
          _asn1_str_cat (name2, sizeof (name2), p->value);
 
964
          p2 = asn1_find_node (node, name2);
 
965
          if (p2 == NULL)
 
966
            {
 
967
              strcpy (_asn1_identifierMissing, p->value);
 
968
              return ASN1_IDENTIFIER_NOT_FOUND;
 
969
            }
 
970
        }
 
971
      else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
 
972
               (p->type & CONST_DEFAULT))
 
973
        {
 
974
          p2 = p->down;
 
975
          if (p2 && (type_field (p2->type) == TYPE_DEFAULT))
 
976
            {
 
977
              _asn1_str_cpy (name2, sizeof (name2), node->name);
 
978
              _asn1_str_cat (name2, sizeof (name2), ".");
 
979
              _asn1_str_cat (name2, sizeof (name2), p2->value);
 
980
              strcpy (_asn1_identifierMissing, p2->value);
 
981
              p2 = asn1_find_node (node, name2);
 
982
              if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
 
983
                  !(p2->type & CONST_ASSIGN))
 
984
                return ASN1_IDENTIFIER_NOT_FOUND;
 
985
              else
 
986
                _asn1_identifierMissing[0] = 0;
 
987
            }
 
988
        }
 
989
      else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
 
990
               (p->type & CONST_ASSIGN))
 
991
        {
 
992
          p2 = p->down;
 
993
          if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
 
994
            {
 
995
              if (p2->value && !isdigit (p2->value[0]))
 
996
                {
 
997
                  _asn1_str_cpy (name2, sizeof (name2), node->name);
 
998
                  _asn1_str_cat (name2, sizeof (name2), ".");
 
999
                  _asn1_str_cat (name2, sizeof (name2), p2->value);
 
1000
                  strcpy (_asn1_identifierMissing, p2->value);
 
1001
                  p2 = asn1_find_node (node, name2);
 
1002
                  if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
 
1003
                      !(p2->type & CONST_ASSIGN))
 
1004
                    return ASN1_IDENTIFIER_NOT_FOUND;
 
1005
                  else
 
1006
                    _asn1_identifierMissing[0] = 0;
 
1007
                }
 
1008
            }
 
1009
        }
 
1010
 
 
1011
      if (p->down)
 
1012
        {
 
1013
          p = p->down;
 
1014
        }
 
1015
      else if (p->right)
 
1016
        p = p->right;
 
1017
      else
 
1018
        {
 
1019
          while (1)
 
1020
            {
 
1021
              p = _asn1_find_up (p);
 
1022
              if (p == node)
 
1023
                {
 
1024
                  p = NULL;
 
1025
                  break;
 
1026
                }
 
1027
              if (p->right)
 
1028
                {
 
1029
                  p = p->right;
 
1030
                  break;
 
1031
                }
 
1032
            }
 
1033
        }
 
1034
    }
 
1035
 
 
1036
  return ASN1_SUCCESS;
 
1037
}
 
1038
 
 
1039
 
 
1040
/******************************************************************/
 
1041
/* Function : _asn1_set_default_tag                               */
 
1042
/* Description: sets the default IMPLICIT or EXPLICIT property in */
 
1043
/*   the tagged elements that don't have this declaration.        */
 
1044
/* Parameters:                                                    */
 
1045
/*   node: pointer to a DEFINITIONS element.                      */
 
1046
/* Return:                                                        */
 
1047
/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to   */
 
1048
/*     a DEFINITIONS element,                                     */
 
1049
/*   otherwise ASN1_SUCCESS                                       */
 
1050
/******************************************************************/
 
1051
asn1_retCode
 
1052
_asn1_set_default_tag (ASN1_TYPE node)
 
1053
{
 
1054
  ASN1_TYPE p;
 
1055
 
 
1056
  if ((node == NULL) || (type_field (node->type) != TYPE_DEFINITIONS))
 
1057
    return ASN1_ELEMENT_NOT_FOUND;
 
1058
 
 
1059
  p = node;
 
1060
  while (p)
 
1061
    {
 
1062
      if ((type_field (p->type) == TYPE_TAG) &&
 
1063
          !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
 
1064
        {
 
1065
          if (node->type & CONST_EXPLICIT)
 
1066
            p->type |= CONST_EXPLICIT;
 
1067
          else
 
1068
            p->type |= CONST_IMPLICIT;
 
1069
        }
 
1070
 
 
1071
      if (p->down)
 
1072
        {
 
1073
          p = p->down;
 
1074
        }
 
1075
      else if (p->right)
 
1076
        p = p->right;
 
1077
      else
 
1078
        {
 
1079
          while (1)
 
1080
            {
 
1081
              p = _asn1_find_up (p);
 
1082
              if (p == node)
 
1083
                {
 
1084
                  p = NULL;
 
1085
                  break;
 
1086
                }
 
1087
              if (p->right)
 
1088
                {
 
1089
                  p = p->right;
 
1090
                  break;
 
1091
                }
 
1092
            }
 
1093
        }
 
1094
    }
 
1095
 
 
1096
  return ASN1_SUCCESS;
 
1097
}
 
1098
 
 
1099
 
 
1100
 
 
1101
static const char *
 
1102
parse_version_number (const char *s, int *number)
 
1103
{
 
1104
  int val = 0;
 
1105
 
 
1106
  if (*s == '0' && isdigit (s[1]))
 
1107
    return NULL;                /* leading zeros are not allowed */
 
1108
  for (; isdigit (*s); s++)
 
1109
    {
 
1110
      val *= 10;
 
1111
      val += *s - '0';
 
1112
    }
 
1113
  *number = val;
 
1114
  return val < 0 ? NULL : s;
 
1115
}
 
1116
 
 
1117
/* The parse version functions were copied from libgcrypt.
 
1118
 */
 
1119
static const char *
 
1120
parse_version_string (const char *s, int *major, int *minor, int *micro)
 
1121
{
 
1122
  s = parse_version_number (s, major);
 
1123
  if (!s || *s != '.')
 
1124
    return NULL;
 
1125
  s++;
 
1126
  s = parse_version_number (s, minor);
 
1127
  if (!s)
 
1128
    return NULL;
 
1129
  if (*s != '.')
 
1130
    {
 
1131
      *micro = 0;
 
1132
      return s;
 
1133
    }
 
1134
  s++;
 
1135
  s = parse_version_number (s, micro);
 
1136
  if (!s)
 
1137
    return NULL;
 
1138
  return s;                     /* patchlevel */
 
1139
}
 
1140
 
 
1141
/**
 
1142
 * asn1_check_version - check for library version
 
1143
 * @req_version: Required version number, or NULL.
 
1144
 *
 
1145
 * Check that the version of the library is at minimum the
 
1146
 * requested one and return the version string; return %NULL if the
 
1147
 * condition is not satisfied.  If a %NULL is passed to this function,
 
1148
 * no check is done, but the version string is simply returned.
 
1149
 *
 
1150
 * See %ASN1_VERSION for a suitable @req_version string.
 
1151
 *
 
1152
 * Return value: Version string of run-time library, or %NULL if the
 
1153
 *   run-time library does not meet the required version number.
 
1154
 */
 
1155
const char *
 
1156
asn1_check_version (const char *req_version)
 
1157
{
 
1158
  const char *ver = ASN1_VERSION;
 
1159
  int my_major, my_minor, my_micro;
 
1160
  int rq_major, rq_minor, rq_micro;
 
1161
  const char *my_plvl, *rq_plvl;
 
1162
 
 
1163
  if (!req_version)
 
1164
    return ver;
 
1165
 
 
1166
  my_plvl = parse_version_string (ver, &my_major, &my_minor, &my_micro);
 
1167
  if (!my_plvl)
 
1168
    return NULL;                /* very strange our own version is bogus */
 
1169
  rq_plvl = parse_version_string (req_version, &rq_major, &rq_minor,
 
1170
                                  &rq_micro);
 
1171
  if (!rq_plvl)
 
1172
    return NULL;                /* req version string is invalid */
 
1173
 
 
1174
  if (my_major > rq_major
 
1175
      || (my_major == rq_major && my_minor > rq_minor)
 
1176
      || (my_major == rq_major && my_minor == rq_minor
 
1177
          && my_micro > rq_micro)
 
1178
      || (my_major == rq_major && my_minor == rq_minor
 
1179
          && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
 
1180
    {
 
1181
      return ver;
 
1182
    }
 
1183
  return NULL;
 
1184
}