… | |
… | |
10 | ASN_INTEGER32 = 0x02, |
10 | ASN_INTEGER32 = 0x02, |
11 | ASN_BIT_STRING = 0x03, |
11 | ASN_BIT_STRING = 0x03, |
12 | ASN_OCTET_STRING = 0x04, |
12 | ASN_OCTET_STRING = 0x04, |
13 | ASN_NULL = 0x05, |
13 | ASN_NULL = 0x05, |
14 | ASN_OBJECT_IDENTIFIER = 0x06, |
14 | ASN_OBJECT_IDENTIFIER = 0x06, |
|
|
15 | ASN_REAL = 0x09, //X |
|
|
16 | ASN_ENUMERATED = 0x0a, //X |
15 | ASN_SEQUENCE = 0x10, |
17 | ASN_SEQUENCE = 0x10, |
|
|
18 | ASN_SET = 0x11, //X |
|
|
19 | ASN_UTC_TIME = 0x17, //X |
|
|
20 | ASN_GENERAL_TIME = 0x18, //X |
16 | |
21 | |
17 | ASN_TAG_BER = 0x1f, |
22 | ASN_TAG_BER = 0x1f, |
18 | ASN_TAG_MASK = 0x1f, |
23 | ASN_TAG_MASK = 0x1f, |
19 | |
24 | |
20 | // primitive/constructed |
25 | // primitive/constructed |
… | |
… | |
27 | ASN_PRIVATE = 0xc0, |
32 | ASN_PRIVATE = 0xc0, |
28 | |
33 | |
29 | ASN_CLASS_MASK = 0xc0, |
34 | ASN_CLASS_MASK = 0xc0, |
30 | ASN_CLASS_SHIFT = 6, |
35 | ASN_CLASS_SHIFT = 6, |
31 | |
36 | |
32 | // ASN_APPLICATION |
37 | // ASN_APPLICATION SNMP |
33 | ASN_IPADDRESS = 0x00, |
38 | ASN_IPADDRESS = 0x00, |
34 | ASN_COUNTER32 = 0x01, |
39 | ASN_COUNTER32 = 0x01, |
35 | ASN_UNSIGNED32 = 0x02, |
40 | ASN_UNSIGNED32 = 0x02, |
36 | ASN_TIMETICKS = 0x03, |
41 | ASN_TIMETICKS = 0x03, |
37 | ASN_OPAQUE = 0x04, |
42 | ASN_OPAQUE = 0x04, |
… | |
… | |
86 | } |
91 | } |
87 | |
92 | |
88 | return 1; |
93 | return 1; |
89 | } |
94 | } |
90 | |
95 | |
|
|
96 | // get_* functions fetch something from the buffer |
|
|
97 | // decode_* functions use get_* fun ctions to decode ber values |
|
|
98 | |
91 | static U8 * |
99 | static U8 * |
92 | getn (int count, const U8 *errres) |
100 | get_n (int count, const U8 *errres) |
93 | { |
101 | { |
94 | if (!need (count)) |
102 | if (!need (count)) |
95 | return (U8 *)errres; |
103 | return (U8 *)errres; |
96 | |
104 | |
97 | U8 *res = cur; |
105 | U8 *res = cur; |
… | |
… | |
101 | |
109 | |
102 | return res; |
110 | return res; |
103 | } |
111 | } |
104 | |
112 | |
105 | static U8 |
113 | static U8 |
106 | get8 (void) |
114 | get_u8 (void) |
107 | { |
115 | { |
108 | if (rem <= 0) |
116 | if (rem <= 0) |
109 | { |
117 | { |
110 | error ("unexpected end of message buffer"); |
118 | error ("unexpected end of message buffer"); |
111 | return 0; |
119 | return 0; |
… | |
… | |
114 | rem--; |
122 | rem--; |
115 | return *cur++; |
123 | return *cur++; |
116 | } |
124 | } |
117 | |
125 | |
118 | static U32 |
126 | static U32 |
119 | getb (void) |
127 | get_ber (void) |
120 | { |
128 | { |
121 | U32 res = 0; |
129 | U32 res = 0; |
122 | |
130 | |
123 | for (;;) |
131 | for (;;) |
124 | { |
132 | { |
125 | U8 c = get8 (); |
133 | U8 c = get_u8 (); |
126 | res = (res << 7) | (c & 0x7f); |
134 | res = (res << 7) | (c & 0x7f); |
127 | |
135 | |
128 | if (!(c & 0x80)) |
136 | if (!(c & 0x80)) |
129 | return res; |
137 | return res; |
130 | } |
138 | } |
131 | } |
139 | } |
132 | |
140 | |
133 | static U32 |
141 | static U32 |
134 | process_length (void) |
142 | get_length (void) |
135 | { |
143 | { |
136 | U32 res = get8 (); |
144 | U32 res = get_u8 (); |
137 | |
145 | |
138 | if (res & 0x80) |
146 | if (res & 0x80) |
139 | { |
147 | { |
140 | int cnt = res & 0x7f; |
148 | int cnt = res & 0x7f; |
141 | res = 0; |
149 | res = 0; |
… | |
… | |
148 | |
156 | |
149 | default: |
157 | default: |
150 | error ("ASN.1 length too long"); |
158 | error ("ASN.1 length too long"); |
151 | return 0; |
159 | return 0; |
152 | |
160 | |
153 | case 4: res = (res << 8) | get8 (); |
161 | case 4: res = (res << 8) | get_u8 (); |
154 | case 3: res = (res << 8) | get8 (); |
162 | case 3: res = (res << 8) | get_u8 (); |
155 | case 2: res = (res << 8) | get8 (); |
163 | case 2: res = (res << 8) | get_u8 (); |
156 | case 1: res = (res << 8) | get8 (); |
164 | case 1: res = (res << 8) | get_u8 (); |
157 | } |
165 | } |
158 | } |
166 | } |
159 | |
167 | |
160 | return res; |
168 | return res; |
161 | } |
169 | } |
162 | |
170 | |
163 | static U32 |
171 | static U32 |
164 | process_integer32 (void) |
172 | get_integer32 (void) |
165 | { |
173 | { |
166 | U32 length = process_length (); |
174 | U32 length = get_length (); |
167 | |
175 | |
168 | if (length <= 0) |
176 | if (length <= 0) |
169 | { |
177 | { |
170 | error ("INTEGER32 length equal to zero"); |
178 | error ("INTEGER32 length equal to zero"); |
171 | return 0; |
179 | return 0; |
172 | } |
180 | } |
173 | |
181 | |
174 | U8 *data = getn (length, 0); |
182 | U8 *data = get_n (length, 0); |
175 | |
183 | |
176 | if (!data) |
184 | if (!data) |
177 | return 0; |
185 | return 0; |
178 | |
186 | |
179 | if (length > 5 || (length > 4 && data [0])) |
187 | if (length > 5 || (length > 4 && data [0])) |
… | |
… | |
189 | |
197 | |
190 | return res; |
198 | return res; |
191 | } |
199 | } |
192 | |
200 | |
193 | static SV * |
201 | static SV * |
194 | process_integer32_sv (void) |
202 | decode_integer32 (void) |
195 | { |
203 | { |
196 | return newSViv ((I32)process_integer32 ()); |
204 | return newSViv ((I32)get_integer32 ()); |
197 | } |
205 | } |
198 | |
206 | |
199 | static SV * |
207 | static SV * |
200 | process_unsigned32_sv (void) |
208 | decode_unsigned32 (void) |
201 | { |
209 | { |
202 | return newSVuv ((U32)process_integer32 ()); |
210 | return newSVuv ((U32)get_integer32 ()); |
203 | } |
211 | } |
204 | |
212 | |
205 | #if IVSIZE >= 8 |
213 | #if IVSIZE >= 8 |
206 | |
214 | |
207 | static U64TYPE |
215 | static U64TYPE |
208 | process_integer64 (void) |
216 | get_integer64 (void) |
209 | { |
217 | { |
210 | U32 length = process_length (); |
218 | U32 length = get_length (); |
211 | |
219 | |
212 | if (length <= 0) |
220 | if (length <= 0) |
213 | { |
221 | { |
214 | error ("INTEGER64 length equal to zero"); |
222 | error ("INTEGER64 length equal to zero"); |
215 | return 0; |
223 | return 0; |
216 | } |
224 | } |
217 | |
225 | |
218 | U8 *data = getn (length, 0); |
226 | U8 *data = get_n (length, 0); |
219 | |
227 | |
220 | if (!data) |
228 | if (!data) |
221 | return 0; |
229 | return 0; |
222 | |
230 | |
223 | if (length > 9 || (length > 8 && data [0])) |
231 | if (length > 9 || (length > 8 && data [0])) |
… | |
… | |
233 | |
241 | |
234 | return res; |
242 | return res; |
235 | } |
243 | } |
236 | |
244 | |
237 | static SV * |
245 | static SV * |
238 | process_integer64_sv (void) |
246 | decode_integer64 (void) |
239 | { |
247 | { |
240 | return newSViv ((I64TYPE)process_integer64 ()); |
248 | return newSViv ((I64TYPE)get_integer64 ()); |
241 | } |
249 | } |
242 | |
250 | |
243 | static SV * |
251 | static SV * |
244 | process_unsigned64_sv (void) |
252 | decode_unsigned64 (void) |
245 | { |
253 | { |
246 | return newSVuv ((U64TYPE)process_integer64 ()); |
254 | return newSVuv ((U64TYPE)get_integer64 ()); |
247 | } |
255 | } |
248 | |
256 | |
249 | #endif |
257 | #endif |
250 | |
258 | |
251 | static SV * |
259 | static SV * |
252 | process_octet_string_sv (void) |
260 | decode_octet_string (void) |
253 | { |
261 | { |
254 | U32 length = process_length (); |
262 | U32 length = get_length (); |
255 | |
263 | |
256 | U8 *data = getn (length, 0); |
264 | U8 *data = get_n (length, 0); |
257 | if (!data) |
265 | if (!data) |
258 | { |
266 | { |
259 | error ("OCTET STRING too long"); |
267 | error ("OCTET STRING too long"); |
260 | return &PL_sv_undef; |
268 | return &PL_sv_undef; |
261 | } |
269 | } |
262 | |
270 | |
263 | return newSVpvn (data, length); |
271 | return newSVpvn (data, length); |
264 | } |
272 | } |
265 | |
273 | |
|
|
274 | // gelper for decode_object_identifier |
266 | static char * |
275 | static char * |
267 | write_uv (char *buf, U32 u) |
276 | write_uv (char *buf, U32 u) |
268 | { |
277 | { |
269 | // the one-digit case is absolutely predominant, so this pays off (hopefully) |
278 | // the one-digit case is absolutely predominant, so this pays off (hopefully) |
270 | if (u < 10) |
279 | if (u < 10) |
… | |
… | |
291 | |
300 | |
292 | return buf; |
301 | return buf; |
293 | } |
302 | } |
294 | |
303 | |
295 | static SV * |
304 | static SV * |
296 | process_object_identifier_sv (void) |
305 | decode_object_identifier (void) |
297 | { |
306 | { |
298 | U32 length = process_length (); |
307 | U32 length = get_length (); |
299 | |
308 | |
300 | if (length <= 0) |
309 | if (length <= 0) |
301 | { |
310 | { |
302 | error ("OBJECT IDENTIFIER length equal to zero"); |
311 | error ("OBJECT IDENTIFIER length equal to zero"); |
303 | return &PL_sv_undef; |
312 | return &PL_sv_undef; |
304 | } |
313 | } |
305 | |
314 | |
306 | U8 *end = cur + length; |
315 | U8 *end = cur + length; |
307 | U32 w = getb (); |
316 | U32 w = get_ber (); |
308 | |
317 | |
309 | static char oid[MAX_OID_STRLEN]; // must be static |
318 | static char oid[MAX_OID_STRLEN]; // must be static |
310 | char *app = oid; |
319 | char *app = oid; |
311 | |
320 | |
312 | app = write_uv (app, (U8)w / 40); |
321 | app = write_uv (app, (U8)w / 40); |
… | |
… | |
314 | app = write_uv (app, (U8)w % 40); |
323 | app = write_uv (app, (U8)w % 40); |
315 | |
324 | |
316 | // we assume an oid component is never > 64 bytes |
325 | // we assume an oid component is never > 64 bytes |
317 | while (cur < end && oid + sizeof (oid) - app > 64) |
326 | while (cur < end && oid + sizeof (oid) - app > 64) |
318 | { |
327 | { |
319 | w = getb (); |
328 | w = get_ber (); |
320 | *app++ = '.'; |
329 | *app++ = '.'; |
321 | app = write_uv (app, w); |
330 | app = write_uv (app, w); |
322 | } |
331 | } |
323 | |
332 | |
324 | return newSVpvn (oid, app - oid); |
333 | return newSVpvn (oid, app - oid); |
325 | } |
334 | } |
326 | |
335 | |
327 | static SV * |
336 | static SV * |
328 | ber_decode () |
337 | decode_ber () |
329 | { |
338 | { |
330 | int identifier = get8 (); |
339 | int identifier = get_u8 (); |
331 | |
340 | |
332 | SV *res; |
341 | SV *res; |
333 | |
342 | |
334 | int constructed = identifier & ASN_CONSTRUCTED; |
343 | int constructed = identifier & ASN_CONSTRUCTED; |
335 | int klass = identifier & ASN_CLASS_MASK; |
344 | int klass = identifier & ASN_CLASS_MASK; |
336 | int tag = identifier & ASN_TAG_MASK; |
345 | int tag = identifier & ASN_TAG_MASK; |
337 | |
346 | |
338 | if (tag == ASN_TAG_BER) |
347 | if (tag == ASN_TAG_BER) |
339 | tag = getb (); |
348 | tag = get_ber (); |
340 | |
349 | |
341 | if (tag == ASN_TAG_BER) |
350 | if (tag == ASN_TAG_BER) |
342 | tag = getb (); |
351 | tag = get_ber (); |
343 | |
352 | |
344 | if (constructed) |
353 | if (constructed) |
345 | { |
354 | { |
346 | U32 len = process_length (); |
355 | U32 len = get_length (); |
347 | U32 seqend = (cur - buf) + len; |
356 | U32 seqend = (cur - buf) + len; |
348 | AV *av = (AV *)sv_2mortal ((SV *)newAV ()); |
357 | AV *av = (AV *)sv_2mortal ((SV *)newAV ()); |
349 | |
358 | |
350 | while (cur < buf + seqend) |
359 | while (cur < buf + seqend) |
351 | av_push (av, ber_decode ()); |
360 | av_push (av, decode_ber ()); |
352 | |
361 | |
353 | if (cur > buf + seqend) |
362 | if (cur > buf + seqend) |
354 | croak ("constructed type %02x overflow (%x %x)\n", identifier, cur - buf, seqend); |
363 | croak ("constructed type %02x overflow (%x %x)\n", identifier, cur - buf, seqend); |
355 | |
364 | |
356 | res = newRV_inc ((SV *)av); |
365 | res = newRV_inc ((SV *)av); |
… | |
… | |
361 | case ASN_NULL: |
370 | case ASN_NULL: |
362 | res = &PL_sv_undef; |
371 | res = &PL_sv_undef; |
363 | break; |
372 | break; |
364 | |
373 | |
365 | case ASN_OBJECT_IDENTIFIER: |
374 | case ASN_OBJECT_IDENTIFIER: |
366 | res = process_object_identifier_sv (); |
375 | res = decode_object_identifier (); |
367 | break; |
376 | break; |
368 | |
377 | |
369 | case ASN_INTEGER32: |
378 | case ASN_INTEGER32: |
370 | res = process_integer32_sv (); |
379 | res = decode_integer32 (); |
371 | break; |
380 | break; |
372 | |
381 | |
373 | case ASN_APPLICATION | ASN_UNSIGNED32: |
382 | case ASN_APPLICATION | ASN_UNSIGNED32: |
374 | case ASN_APPLICATION | ASN_COUNTER32: |
383 | case ASN_APPLICATION | ASN_COUNTER32: |
375 | case ASN_APPLICATION | ASN_TIMETICKS: |
384 | case ASN_APPLICATION | ASN_TIMETICKS: |
376 | res = process_unsigned32_sv (); |
385 | res = decode_unsigned32 (); |
377 | break; |
386 | break; |
378 | |
387 | |
379 | #if 0 // handled by default case |
388 | #if 0 // handled by default case |
380 | case ASN_OCTET_STRING: |
389 | case ASN_OCTET_STRING: |
381 | case ASN_APPLICATION | ASN_IPADDRESS: |
390 | case ASN_APPLICATION | ASN_IPADDRESS: |
382 | case ASN_APPLICATION | ASN_OPAQUE: |
391 | case ASN_APPLICATION | ASN_OPAQUE: |
383 | res = process_octet_string_sv (); |
392 | res = decode_octet_string (); |
384 | break; |
393 | break; |
385 | #endif |
394 | #endif |
386 | |
395 | |
387 | case ASN_APPLICATION | ASN_COUNTER64: |
396 | case ASN_APPLICATION | ASN_COUNTER64: |
388 | res = process_integer64_sv (); |
397 | res = decode_integer64 (); |
389 | break; |
398 | break; |
390 | |
399 | |
391 | default: |
400 | default: |
392 | res = process_octet_string_sv (); |
401 | res = decode_octet_string (); |
393 | break; |
402 | break; |
394 | } |
403 | } |
395 | |
404 | |
396 | AV *av = newAV (); |
405 | AV *av = newAV (); |
397 | av_fill (av, BER_ARRAYSIZE - 1); |
406 | av_fill (av, BER_ARRAYSIZE - 1); |
… | |
… | |
454 | { |
463 | { |
455 | buf = SvPVbyte (ber, len); |
464 | buf = SvPVbyte (ber, len); |
456 | cur = buf; |
465 | cur = buf; |
457 | rem = len; |
466 | rem = len; |
458 | |
467 | |
459 | RETVAL = ber_decode (); |
468 | RETVAL = decode_ber (); |
460 | } |
469 | } |
461 | OUTPUT: RETVAL |
470 | OUTPUT: RETVAL |
462 | |
471 | |
463 | void |
472 | void |
464 | ber_is (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef) |
473 | ber_is (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef) |