ASN1: Fix NULL pointer dereference on stack allocation failure.
[silc.git] / lib / silcasn1 / silcasn1.c
1 /*
2
3   silcasn1.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21 #include "silcasn1.h"
22 #include "silcber.h"
23
24 /* Allocate ASN.1 context. */
25
26 SilcAsn1 silc_asn1_alloc(void)
27 {
28   SilcAsn1 asn1 = silc_calloc(1, sizeof(*asn1));
29   if (!asn1)
30     return NULL;
31
32   if (!silc_asn1_init(asn1))
33     return NULL;
34
35   return asn1;
36 }
37
38 /* Free ASN.1 context */
39
40 void silc_asn1_free(SilcAsn1 asn1)
41 {
42   silc_asn1_uninit(asn1);
43   silc_free(asn1);
44 }
45
46 /* Init pre-allocated ASN.1 context */
47
48 SilcBool silc_asn1_init(SilcAsn1 asn1)
49 {
50   asn1->stack1 = silc_stack_alloc(768);
51   if (!asn1->stack1)
52     return FALSE;
53
54   asn1->stack2 = silc_stack_alloc(768);
55   if (!asn1->stack2) {
56     silc_stack_free(asn1->stack1);
57     return FALSE;
58   }
59
60   asn1->accumul = 0;
61
62   return TRUE;
63 }
64
65 /* Uninit ASN.1 context */
66
67 void silc_asn1_uninit(SilcAsn1 asn1)
68 {
69   silc_stack_free(asn1->stack1);
70   silc_stack_free(asn1->stack2);
71 }
72
73 #if defined(SILC_DEBUG)
74 /* Returns string representation of a tag */
75
76 const char *silc_asn1_tag_name(SilcAsn1Tag tag)
77 {
78   switch (tag) {
79   case SILC_ASN1_END:
80     return "END";
81   case SILC_ASN1_TAG_OPTS:
82     return "";
83   case SILC_ASN1_TAG_CHOICE:
84     return "choice";
85   case SILC_ASN1_TAG_ANY:
86     return "any";
87   case SILC_ASN1_TAG_ANY_PRIMITIVE:
88     return "any primitive";
89   case SILC_ASN1_TAG_SEQUENCE_OF:
90     return "sequence of";
91   case SILC_ASN1_TAG_SEQUENCE:
92     return "sequence";
93   case SILC_ASN1_TAG_SET:
94     return "set";
95   case SILC_ASN1_TAG_INTEGER:
96     return "integer";
97   case SILC_ASN1_TAG_SHORT_INTEGER:
98     return "short integer";
99   case SILC_ASN1_TAG_OID:
100     return "oid";
101   case SILC_ASN1_TAG_BOOLEAN:
102     return "boolean";
103   case SILC_ASN1_TAG_OCTET_STRING:
104     return "octet-string";
105   case SILC_ASN1_TAG_BIT_STRING:
106     return "bit-string";
107   case SILC_ASN1_TAG_NULL:
108     return "null";
109   case SILC_ASN1_TAG_ENUM:
110     return "enum";
111   case SILC_ASN1_TAG_UTC_TIME:
112     return "utc-time";
113   case SILC_ASN1_TAG_GENERALIZED_TIME:
114     return "generalized-time";
115   case SILC_ASN1_TAG_UTF8_STRING:
116     return "utf8-string";
117   case SILC_ASN1_TAG_NUMERIC_STRING:
118     return "numeric-string";
119   case SILC_ASN1_TAG_PRINTABLE_STRING:
120     return "printable-string";
121   case SILC_ASN1_TAG_IA5_STRING:
122     return "ia5-string";
123   case SILC_ASN1_TAG_VISIBLE_STRING:
124     return "visible-string";
125   case SILC_ASN1_TAG_UNIVERSAL_STRING:
126     return "universal-string";
127   case SILC_ASN1_TAG_UNRESTRICTED_STRING:
128     return "unrestricted-string";
129   case SILC_ASN1_TAG_BMP_STRING:
130     return "bmp-string";
131   case SILC_ASN1_TAG_ODE:
132     return "ode";
133   case SILC_ASN1_TAG_ETI:
134     return "eti";
135   case SILC_ASN1_TAG_REAL:
136     return "real";
137   case SILC_ASN1_TAG_EMBEDDED:
138     return "embedded";
139   case SILC_ASN1_TAG_ROI:
140     return "roi";
141   case SILC_ASN1_TAG_TELETEX_STRING:
142     return "teletex-string";
143   case SILC_ASN1_TAG_VIDEOTEX_STRING:
144     return "videotex-string";
145   case SILC_ASN1_TAG_GRAPHIC_STRING:
146     return "graphic-string";
147   case SILC_ASN1_TAG_GENERAL_STRING:
148     return "general-string";
149   default:
150     break;
151   }
152   return "unknown";
153 }
154 #endif /* SILC_DEBUG */
155
156 #ifdef SILC_DIST_TOOLKIT
157 #ifdef SILC_DEBUG
158 /* Dumps the ASN.1 data block into standard output (stdout). */
159
160 SilcBool silc_asn1_dump(SilcAsn1 asn1, SilcBuffer src)
161 {
162   SilcBool ret = FALSE;
163   SilcBerEncoding renc;
164   SilcUInt32 rtag;
165   const unsigned char *rdata;
166   SilcUInt32 rdata_len, len = 0;
167   SilcBool rindef;
168
169   SILC_LOG_DEBUG(("Dumping ASN.1"));
170
171   while (silc_buffer_len(src)) {
172     /* Decode the BER block */
173     ret = silc_ber_decode(src, NULL, &renc, &rtag, &rdata,
174                           &rdata_len, &rindef, &len);
175     if (!ret) {
176       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
177       return FALSE;
178     }
179
180     fprintf(stdout, "Type %s [%d]\n",
181             silc_asn1_tag_name(rtag), rtag);
182
183     if (renc == SILC_BER_ENC_PRIMITIVE)
184       len = len + rdata_len;
185     else
186       len = len;
187
188     if (len)
189       silc_buffer_pull(src, len);
190   }
191
192   return TRUE;
193 }
194 #endif /* SILC_DEBUG */
195 #endif /* SILC_DIST_TOOLKIT */