ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-BER-XS/XS.xs
(Generate patch)

Comparing Convert-BER-XS/XS.xs (file contents):
Revision 1.1 by root, Fri Apr 19 16:19:36 2019 UTC vs.
Revision 1.2 by root, Fri Apr 19 16:49:02 2019 UTC

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
91static U8 * 99static U8 *
92getn (int count, const U8 *errres) 100get_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
105static U8 113static U8
106get8 (void) 114get_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
118static U32 126static U32
119getb (void) 127get_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
133static U32 141static U32
134process_length (void) 142get_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
163static U32 171static U32
164process_integer32 (void) 172get_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
193static SV * 201static SV *
194process_integer32_sv (void) 202decode_integer32 (void)
195{ 203{
196 return newSViv ((I32)process_integer32 ()); 204 return newSViv ((I32)get_integer32 ());
197} 205}
198 206
199static SV * 207static SV *
200process_unsigned32_sv (void) 208decode_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
207static U64TYPE 215static U64TYPE
208process_integer64 (void) 216get_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
237static SV * 245static SV *
238process_integer64_sv (void) 246decode_integer64 (void)
239{ 247{
240 return newSViv ((I64TYPE)process_integer64 ()); 248 return newSViv ((I64TYPE)get_integer64 ());
241} 249}
242 250
243static SV * 251static SV *
244process_unsigned64_sv (void) 252decode_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
251static SV * 259static SV *
252process_octet_string_sv (void) 260decode_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
266static char * 275static char *
267write_uv (char *buf, U32 u) 276write_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
295static SV * 304static SV *
296process_object_identifier_sv (void) 305decode_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
327static SV * 336static SV *
328ber_decode () 337decode_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
463void 472void
464ber_is (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef) 473ber_is (SV *tuple, SV *klass = &PL_sv_undef, SV *tag = &PL_sv_undef, SV *constructed = &PL_sv_undef, SV *data = &PL_sv_undef)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines