1 /**
2 * asn.cpp
3 * This file is part of the YATE Project http://YATE.null.ro
4 *
5 * ASN.1 Library
6 *
7 * Yet Another Telephony Engine - a fully featured software PBX and IVR
8 * Copyright (C) 2004-2014 Null Team
9 *
10 * This software is distributed under multiple licenses;
11 * see the COPYING file in the main directory for licensing
12 * information for this specific distribution.
13 *
14 * This use of this software may be subject to additional restrictions.
15 * See the LEGAL file in the main directory for details.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #include "yateasn.h"
23
24 using namespace TelEngine;
25
26 static String s_libName = "ASNLib";
27
ASNLib()28 ASNLib::ASNLib()
29 {}
30
~ASNLib()31 ASNLib::~ASNLib()
32 {}
33
decodeLength(DataBlock & data)34 int ASNLib::decodeLength(DataBlock& data) {
35
36 XDebug(s_libName.c_str(),DebugAll,"::decodeLength() - from data='%p'",&data);
37 int length = 0;
38 uint8_t lengthByte = data[0];
39
40 if (lengthByte & ASN_LONG_LENGTH) { // the length is represented on more than one byte
41
42 lengthByte &= ~ASN_LONG_LENGTH; /* turn MSB off */
43 if (lengthByte == 0) {
44 data.cut(-1);
45 return IndefiniteForm;
46 }
47
48 if (lengthByte > sizeof(int))
49 return InvalidLengthOrTag;
50
51 for (int i = 0 ; i < lengthByte ; i++)
52 length = (length << 8) + data[1 + i];
53
54 data.cut(-lengthByte - 1);
55 return length;
56
57 } else { // one byte for length
58 length = (int) lengthByte;
59 data.cut(-1);
60 return length;
61 }
62 }
63
buildLength(DataBlock & data)64 DataBlock ASNLib::buildLength(DataBlock& data)
65 {
66 XDebug(s_libName.c_str(),DebugAll,"::buildLength() - encode length=%d",data.length());
67 DataBlock lenDb;
68 if (data.length() < 0)
69 return lenDb;
70 if (data.length() < ASN_LONG_LENGTH) {
71 uint8_t l = data.length();
72 lenDb.append(&l, 1);
73 return lenDb;
74 }
75 else {
76 uint8_t longLen = ASN_LONG_LENGTH;
77 int len = data.length();
78 while (len > 0) {
79 uint8_t v = len & 0xFF;
80 lenDb.insert(DataBlock(&v,1));
81 len >>= 8;
82 }
83 longLen |= lenDb.length();
84 lenDb.insert(DataBlock(&longLen,1));
85 return lenDb;
86 }
87 return lenDb;
88 }
89
matchEOC(DataBlock & data)90 int ASNLib::matchEOC(DataBlock& data)
91 {
92 /**
93 * EoC = 00 00
94 */
95 XDebug(s_libName.c_str(),DebugAll,"::matchEOC() in data='%p'",&data);
96 if (data.length() < 2)
97 return InvalidLengthOrTag;
98 if (data[0] == 0 && data[1] == 0) {
99 data.cut(-2);
100 return 2;
101 }
102 return InvalidLengthOrTag;
103 }
104
105
parseUntilEoC(DataBlock & data,int length)106 int ASNLib::parseUntilEoC(DataBlock& data, int length)
107 {
108 if (length >= (int)data.length() || ASNLib::matchEOC(data) > 0)
109 return length;
110 while (data.length() && ASNLib::matchEOC(data) < 0) {
111 // compute tag portion length
112 AsnTag tag;
113 AsnTag::decode(tag,data);
114 length += tag.coding().length();
115 data.cut(-(int)tag.coding().length());
116 // compute length portion length
117 int initLen = data.length();
118 int len = ASNLib::decodeLength(data);
119 length += initLen - data.length();
120
121 bool checkEoC = (len == ASNLib::IndefiniteForm);
122 if (!checkEoC && len < 0)
123 return length;
124
125 if (checkEoC) {
126 length = parseUntilEoC(data,length);
127 if (ASNLib::matchEOC(data) > 0)
128 length += 2;
129 }
130 else {
131 length += len;
132 data.cut(-len);
133 }
134 }
135 return length;
136 }
137
decodeBoolean(DataBlock & data,bool * val,bool tagCheck)138 int ASNLib::decodeBoolean(DataBlock& data, bool* val, bool tagCheck)
139 {
140 /**
141 * boolean = 0x01 length byte (byte == 0 => false, byte != 0 => true)
142 */
143 XDebug(s_libName.c_str(),DebugAll,"::decodeBoolean() from data='%p'",&data);
144 if (data.length() < 2)
145 return InvalidLengthOrTag;
146 #ifdef DEBUG
147 unsigned int initLen = data.length();
148 #endif
149 if (tagCheck) {
150 int type = data[0];
151 if ((type != BOOLEAN)) {
152 XDebug(s_libName.c_str(),DebugAll,"::decodeBoolean() - Invalid Tag in data='%p'",&data);
153 return InvalidLengthOrTag;
154 }
155 data.cut(-1);
156 }
157 int length = decodeLength(data);
158 if (length < 0) {
159 DDebug(s_libName.c_str(),DebugAll,"::decodeBoolean() - Invalid Length in data='%p'",&data);
160 return length;
161 }
162
163 if ((unsigned int)length > data.length() || length != 1) {
164 DDebug(s_libName.c_str(),DebugAll,"::decodeBoolean() - Invalid Length in data='%p'",&data);
165 return InvalidLengthOrTag;
166 }
167 if (!val) {
168 data.cut(-1);
169 DDebug(s_libName.c_str(),DebugAll,"::decodeBoolean() - Invalid buffer for return data");
170 return InvalidContentsError;
171 }
172 *val = false;
173 if ((data[0] & 0xFF) != 0)
174 *val = true;
175 data.cut(-1);
176 #ifdef DEBUG
177 Debug(s_libName.c_str(),DebugAll,"::decodeBoolean() - decoded boolean value from data='%p', consumed %u bytes",
178 &data, initLen - data.length());
179 #endif
180 return length;
181 }
182
decodeInteger(DataBlock & data,u_int64_t & intVal,unsigned int bytes,bool tagCheck)183 int ASNLib::decodeInteger(DataBlock& data, u_int64_t& intVal, unsigned int bytes, bool tagCheck)
184 {
185 /**
186 * integer = 0x02 length byte {byte}*
187 */
188 XDebug(s_libName.c_str(),DebugAll,"::decodeInteger() from data='%p'",&data);
189 int64_t value = 0;
190 if (data.length() < 2)
191 return InvalidLengthOrTag;
192 #ifdef DEBUG
193 unsigned int initLen = data.length();
194 #endif
195 if (tagCheck) {
196 int type = data[0];
197 if ((type != INTEGER)) {
198 XDebug(s_libName.c_str(),DebugAll,"::decodeInteger() - Invalid Tag in data='%p'",&data);
199 return InvalidLengthOrTag;
200 }
201 data.cut(-1);
202 }
203 int length = decodeLength(data);
204 if (length < 0) {
205 DDebug(s_libName.c_str(),DebugAll,"::decodeInteger() - Invalid Length in data='%p'",&data);
206 return length;
207 }
208
209 if ((unsigned int)length > data.length()) {
210 DDebug(s_libName.c_str(),DebugAll,"::decodeInteger() - Invalid Length in data='%p'",&data);
211 return InvalidLengthOrTag;
212 }
213
214 if ((unsigned int)length > bytes) {
215 DDebug(s_libName.c_str(),DebugAll,"::decodeInteger() - Invalid Length: decoded length=%d greater than requested length=%u in data='%p'",
216 length,bytes,&data);
217 return InvalidLengthOrTag;
218 }
219
220 if (data[0] & 0x80)
221 value = -1; /* integer is negative */
222 int j = 0;
223 while (j < length) {
224 value = (value << 8) | data[j];
225 j++;
226 }
227 intVal = (u_int64_t) value;
228 data.cut(-length);
229 #ifdef DEBUG
230 Debug(s_libName.c_str(),DebugAll,"::decodeInteger() - decoded integer value from data='%p', consumed %u bytes",
231 &data, initLen - data.length());
232 #endif
233 return length;
234 }
235
decodeUINT8(DataBlock & data,u_int8_t * intVal,bool tagCheck)236 int ASNLib::decodeUINT8(DataBlock& data, u_int8_t* intVal, bool tagCheck)
237 {
238 XDebug(s_libName.c_str(),DebugAll,"::decodeUINT8()");
239 u_int64_t val;
240 int l = decodeInteger(data,val,sizeof(u_int8_t),tagCheck);
241 if (!intVal) {
242 DDebug(s_libName.c_str(),DebugAll,"::decodeUINT8() - Invalid buffer for return data");
243 return InvalidContentsError;
244 }
245 *intVal = (u_int8_t) val;
246 return l;
247 }
248
decodeUINT16(DataBlock & data,u_int16_t * intVal,bool tagCheck)249 int ASNLib::decodeUINT16(DataBlock& data, u_int16_t* intVal, bool tagCheck)
250 {
251 XDebug(s_libName.c_str(),DebugAll,"::decodeUINT16() from data='%p'",&data);
252 u_int64_t val;
253 int l = decodeInteger(data,val,sizeof(u_int16_t),tagCheck);
254 if (!intVal) {
255 DDebug(s_libName.c_str(),DebugAll,"::decodeUINT16() - Invalid buffer for return data");
256 return InvalidContentsError;
257 }
258 *intVal = (u_int16_t) val;
259 return l;
260 }
261
decodeUINT32(DataBlock & data,u_int32_t * intVal,bool tagCheck)262 int ASNLib::decodeUINT32(DataBlock& data, u_int32_t* intVal, bool tagCheck)
263 {
264 XDebug(s_libName.c_str(),DebugAll,"::decodeUINT32() from data='%p'",&data);
265 u_int64_t val;
266 int l = decodeInteger(data,val,sizeof(u_int32_t),tagCheck);
267 if (!intVal) {
268 DDebug(s_libName.c_str(),DebugAll,"::decodeUINT32() - Invalid buffer for return data");
269 return InvalidContentsError;
270 }
271 *intVal = (u_int32_t) val;
272 return l;
273 }
274
decodeUINT64(DataBlock & data,u_int64_t * intVal,bool tagCheck)275 int ASNLib::decodeUINT64(DataBlock& data, u_int64_t* intVal, bool tagCheck)
276 {
277 XDebug(s_libName.c_str(),DebugAll,"::decodeUINT64() from data='%p'",&data);
278 u_int64_t val;
279 int l = decodeInteger(data,val,sizeof(u_int64_t),tagCheck);
280 if (!intVal) {
281 DDebug(s_libName.c_str(),DebugAll,"::decodeUINT64() - Invalid buffer for return data");
282 return InvalidContentsError;
283 }
284 *intVal = val;
285 return l;
286 }
287
decodeINT8(DataBlock & data,int8_t * intVal,bool tagCheck)288 int ASNLib::decodeINT8(DataBlock& data, int8_t* intVal, bool tagCheck)
289 {
290 XDebug(s_libName.c_str(),DebugAll,"::decodeINT8() from data='%p'",&data);
291 u_int64_t val;
292 int l = decodeInteger(data,val,sizeof(int8_t),tagCheck);
293 if (!intVal) {
294 DDebug(s_libName.c_str(),DebugAll,"::decodeINT8() - Invalid buffer for return data");
295 return InvalidContentsError;
296 }
297 *intVal = (int8_t) val;
298 return l;
299 }
300
decodeINT16(DataBlock & data,int16_t * intVal,bool tagCheck)301 int ASNLib::decodeINT16(DataBlock& data, int16_t* intVal, bool tagCheck)
302 {
303 XDebug(s_libName.c_str(),DebugAll,"::decodeINT16() from data='%p'",&data);
304 u_int64_t val;
305 int l = decodeInteger(data,val,sizeof(int16_t),tagCheck);
306 if (!intVal) {
307 DDebug(s_libName.c_str(),DebugAll,"::decodeINT16() - Invalid buffer for return data");
308 return InvalidContentsError;
309 }
310 *intVal = (int16_t) val;
311 return l;
312 }
313
decodeINT32(DataBlock & data,int32_t * intVal,bool tagCheck)314 int ASNLib::decodeINT32(DataBlock& data, int32_t* intVal, bool tagCheck)
315 {
316 XDebug(s_libName.c_str(),DebugAll,"::decodeINT32() from data='%p'",&data);
317 u_int64_t val;
318 int l = decodeInteger(data,val,sizeof(int32_t),tagCheck);
319 if (!intVal) {
320 DDebug(s_libName.c_str(),DebugAll,"::decodeINT32() - Invalid buffer for return data");
321 return InvalidContentsError;
322 }
323 *intVal = (int32_t) val;
324 return l;
325 }
326
decodeINT64(DataBlock & data,int64_t * intVal,bool tagCheck)327 int ASNLib::decodeINT64(DataBlock& data, int64_t* intVal, bool tagCheck)
328 {
329 XDebug(s_libName.c_str(),DebugAll,"::decodeINT64() from data='%p'",&data);
330 u_int64_t val;
331 int l = decodeInteger(data,val,sizeof(int64_t),tagCheck);
332 if (!intVal) {
333 DDebug(s_libName.c_str(),DebugAll,"::decodeINT64() - Invalid buffer for return data");
334 return InvalidContentsError;
335 }
336 *intVal = val;
337 return l;
338 }
339
decodeBitString(DataBlock & data,String * val,bool tagCheck)340 int ASNLib::decodeBitString(DataBlock& data, String* val, bool tagCheck)
341 {
342 /**
343 * bitstring ::= 0x03 asnlength unusedBytes {byte}*
344 */
345 XDebug(s_libName.c_str(),DebugAll, "::decodeBitString() from data='%p'",&data);
346 if (data.length() < 2)
347 return InvalidLengthOrTag;
348 #ifdef DEBUG
349 unsigned int initLen = data.length();
350 #endif
351 if (tagCheck) {
352 int type = data[0];
353 if ((type != BIT_STRING)) {
354 XDebug(s_libName.c_str(),DebugAll,"::decodeBitString() - Invalid Tag in data='%p'",&data);
355 return InvalidLengthOrTag;
356 }
357 data.cut(-1);
358 }
359 int length = decodeLength(data);
360 if (length < 0) {
361 DDebug(s_libName.c_str(),DebugAll,"::decodeBitString() - Invalid Length in data='%p'",&data);
362 return length;
363 }
364
365 if ((unsigned int)length > data.length()) {
366 DDebug(s_libName.c_str(),DebugAll,"::decodeBitString() - Invalid Length in data='%p'",&data);
367 return InvalidLengthOrTag;
368 }
369
370 if (data[0] > 7){
371 DDebug(s_libName.c_str(),DebugAll, "::decodeBitString() - Invalid bitstring, unused bytes > 7 in data='%p'",&data);
372 return InvalidLengthOrTag;
373 }
374 int unused = data[0];
375 data.cut(-1);
376 length--;
377 int j = 0;
378 if (!val) {
379 DDebug(s_libName.c_str(),DebugAll,"::decodeBitString() - Invalid buffer for return data");
380 data.cut(-length);
381 return InvalidContentsError;
382 }
383 *val = "";
384 while (j < length) {
385 uint8_t byte = data[j];
386 for (int i = 7; i > -1; i--) {
387 int c = (byte >> i) % 2;
388 *val += c;
389 }
390 j++;
391 }
392 *val = val->substr(0, length * 8 - unused);
393 data.cut(-length);
394 #ifdef DEBUG
395 Debug(s_libName.c_str(),DebugAll,"::decodeBitString() - decoded bit string value from data='%p', consumed %u bytes",
396 &data, initLen - data.length());
397 #endif
398 return length;
399 }
400
decodeOctetString(DataBlock & db,OctetString * strVal,bool tagCheck)401 int ASNLib::decodeOctetString(DataBlock& db, OctetString* strVal, bool tagCheck)
402 {
403 /**
404 * octet string ::= 0x04 asnlength {byte}*
405 */
406 XDebug(s_libName.c_str(),DebugAll,":decodeOctetString() from data='%p'",&db);
407 if (db.length() < 2)
408 return InvalidLengthOrTag;
409 #ifdef DEBUG
410 unsigned int initLen = db.length();
411 #endif
412 if (tagCheck) {
413 int type = db[0];
414 if (type != OCTET_STRING) {
415 XDebug(s_libName.c_str(),DebugAll,"::decodeOctetString() - Invalid Tag in data='%p'",&db);
416 return InvalidLengthOrTag;
417 }
418 db.cut(-1);
419 }
420 int length = decodeLength(db);
421 if (length < 0) {
422 DDebug(s_libName.c_str(),DebugAll,"::decodeOctetString() - Invalid Length in data='%p'",&db);
423 return length;
424 }
425 if ((unsigned int)length > db.length()) {
426 DDebug(s_libName.c_str(),DebugAll,"::decodeOctetString() - Invalid Length in data='%p'",&db);
427 return InvalidLengthOrTag;
428 }
429 if (!strVal) {
430 DDebug(s_libName.c_str(),DebugAll,"::decodeOctetString() - Invalid buffer for return data");
431 return InvalidContentsError;
432 }
433 strVal->assign((void*)db.data(0,length),length);
434 db.cut(-length);
435 #ifdef DEBUG
436 Debug(s_libName.c_str(),DebugAll,"::decodeOctetString() - decoded octet string value from data='%p', consumed %u bytes",
437 &db, initLen - db.length());
438 #endif
439 return length;
440 }
441
decodeNull(DataBlock & data,bool tagCheck)442 int ASNLib::decodeNull(DataBlock& data, bool tagCheck)
443 {
444 /**
445 * ASN.1 null := 0x05 00
446 */
447 XDebug(s_libName.c_str(),DebugAll,"::decodeNull() from data='%p'",&data);
448 if (tagCheck) {
449 if (data.length() < 2)
450 return InvalidLengthOrTag;
451
452 if (data[0] != NULL_ID) {
453 XDebug(s_libName.c_str(),DebugAll, "::decodeNull() - Invalid Tag in data='%p'",&data);
454 return InvalidLengthOrTag;
455 }
456 data.cut(-1);
457 }
458 int length = decodeLength(data);
459 if (length != 0) {
460 DDebug(s_libName.c_str(),DebugAll,"::decodeNull() - Invalid Length in data='%p'",&data);
461 return InvalidLengthOrTag;;
462 }
463 DDebug(s_libName.c_str(),DebugAll,"::decodeNull() - decoded null value from data='%p', consumed %u bytes",
464 &data, (tagCheck ? 2 : 1));
465 return length;
466 }
467
decodeOID(DataBlock & data,ASNObjId * obj,bool tagCheck)468 int ASNLib::decodeOID(DataBlock& data, ASNObjId* obj, bool tagCheck)
469 {
470 /**
471 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
472 * subidentifier ::= {leadingbyte}* lastbyte
473 * leadingbyte ::= 1 7bites
474 * lastbyte ::= 0 7bites
475 */
476 XDebug(s_libName.c_str(),DebugAll,"::decodeOID() from data='%p'",&data);
477 if (data.length() < 2)
478 return InvalidLengthOrTag;
479 #ifdef DEBUG
480 unsigned int initLen = data.length();
481 #endif
482 if (tagCheck) {
483 if (data[0] != OBJECT_ID) {
484 XDebug(s_libName.c_str(),DebugAll,"::decodeOID() - Invalid Tag in data='%p'",&data);
485 return InvalidLengthOrTag;
486 }
487 data.cut(-1);
488 }
489 int length = decodeLength(data);
490 if (length < 0) {
491 DDebug(s_libName.c_str(),DebugAll,"::decodeOID() - Invalid Length in data='%p'",&data);
492 return length;
493 }
494
495 if ((unsigned int)length > data.length()) {
496 DDebug(s_libName.c_str(),DebugAll,"::decodeOID() - Invalid Length in data='%p'",&data);
497 return InvalidLengthOrTag;
498 }
499
500 if (length == 0) {
501 obj = 0;
502 return length;
503 }
504
505 int j = 0;
506 String oid = "";
507 unsigned int longNo = 0;
508 while (j < length) {
509 // first byte contains 2 identifiers : x,y. The byte is 40 * x + y . x can only be 0,1,2 so if x > 2, x stays 2 and the rest goes into y
510 if (j == 0) {
511 unsigned int x = data[j] / 40;
512 unsigned int y = data[j] % 40;
513 if (x > 2) {
514 y = (x - 2) * 40 + y;
515 x = 2;
516 }
517 oid += x;
518 oid += ".";
519 oid += y;
520 oid += ".";
521 }
522 else {
523 uint8_t byte = data[j];
524 longNo += byte & ~ASN_BIT8;
525 if ((byte & ASN_BIT8) == ASN_BIT8)
526 longNo <<= 7;
527 else {
528 oid += longNo;
529 longNo = 0;
530 if (j != length -1)
531 oid += ".";
532 }
533 }
534 j++;
535 }
536 data.cut(-length);
537 if (!obj) {
538 DDebug(s_libName.c_str(),DebugAll,"::decodeOID() - Invalid buffer for return data");
539 return InvalidContentsError;
540 }
541 *obj = oid;
542 #ifdef DEBUG
543 Debug(s_libName.c_str(),DebugAll,"::decodeOID() - decoded object ID from data='%p', consumed %u bytes",
544 &data, initLen - data.length());
545 #endif
546 return length;
547 }
548
decodeReal(DataBlock & db,float * realVal,bool tagCheck)549 int ASNLib::decodeReal(DataBlock& db, float* realVal, bool tagCheck)
550 {
551 if (db.length() < 2)
552 return InvalidLengthOrTag;
553 unsigned int initLen = db.length();
554 if (tagCheck) {
555 if (db[0] != REAL) {
556 XDebug(s_libName.c_str(),DebugAll,"::decodeReal() - Invalid Tag in data='%p'",&db);
557 return InvalidLengthOrTag;
558 }
559 db.cut(-1);
560 }
561 int length = decodeLength(db);
562 if (length < 0) {
563 DDebug(s_libName.c_str(),DebugAll,"::decodeReal() - Invalid Length in data='%p'",&db);
564 return length;
565 }
566 if ((unsigned int)length > db.length()) {
567 DDebug(s_libName.c_str(),DebugAll,"::decodeReal() - Invalid Length in data='%p'",&db);
568 return InvalidLengthOrTag;
569 }
570 db.cut(-length);
571 Debug(s_libName.c_str(),DebugInfo,"::decodeReal() - real value decoding not implemented, skipping over the %u bytes of the encoding",
572 initLen - db.length());
573 return 0;
574 }
575
decodeString(DataBlock & data,String * str,int * type,bool tagCheck)576 int ASNLib::decodeString(DataBlock& data, String* str, int* type, bool tagCheck)
577 {
578 XDebug(s_libName.c_str(),DebugAll,"::decodeString() from data='%p'",&data);
579 if (data.length() < 2)
580 return InvalidLengthOrTag;
581 #ifdef DEBUG
582 unsigned int initLen = data.length();
583 #endif
584 if (tagCheck) {
585 if (data[0] != NUMERIC_STR ||
586 data[0] != PRINTABLE_STR ||
587 data[0] != IA5_STR ||
588 data[0] != VISIBLE_STR
589 ) {
590 XDebug(s_libName.c_str(),DebugAll,"::decodeString() - Invalid Tag in data='%p'",&data);
591 return InvalidLengthOrTag;
592 }
593 if (type)
594 *type = data[0];
595 data.cut(-1);
596 }
597 int length = decodeLength(data);
598 if (length < 0) {
599 DDebug(s_libName.c_str(),DebugAll,"::decodeString() -Invalid Length in data='%p'",&data);
600 return length;
601 }
602
603 if ((unsigned int)length > data.length()) {
604 DDebug(s_libName.c_str(),DebugAll,"::decodeString() -Invalid Length in data='%p'",&data);
605 return InvalidLengthOrTag;
606 }
607
608 String var = "";
609 for (int i = 0; i < length; i++)
610 var += (char) (data[i] & 0x7f);
611 data.cut(-length);
612 if (!str || !type) {
613 DDebug(s_libName.c_str(),DebugAll,"::decodeString() - Invalid buffer for return data");
614 return InvalidContentsError;
615 }
616 *str = var;
617 #ifdef DEBUG
618 Debug(s_libName.c_str(),DebugInfo,"::decodeString() - decode string value from data='%p', consumed %u bytes",
619 &data,initLen - data.length());
620 #endif
621 return length;
622 }
623
624
decodeUtf8(DataBlock & data,String * str,bool tagCheck)625 int ASNLib::decodeUtf8(DataBlock& data, String* str, bool tagCheck)
626 {
627 XDebug(s_libName.c_str(),DebugAll,"::decodeUtf8() from data='%p'",&data);
628 if (data.length() < 2)
629 return InvalidLengthOrTag;
630 #ifdef DEBUG
631 unsigned int initLen = data.length();
632 #endif
633 if (tagCheck) {
634 if (data[0] != UTF8_STR) {
635 XDebug(s_libName.c_str(),DebugAll,"::decodeUtf8() - Invalid Tag in data='%p'",&data);
636 return InvalidLengthOrTag;
637 }
638 data.cut(-1);
639 }
640 int length = decodeLength(data);
641 if (length < 0) {
642 DDebug(s_libName.c_str(),DebugAll,"::decodeUtf8() -Invalid Length in data='%p'",&data);
643 return length;
644 }
645
646 if ((unsigned int)length > data.length()) {
647 Debug(s_libName.c_str(),DebugAll,"::decodeUtf8() - Invalid Length in data='%p'",&data);
648 return InvalidLengthOrTag;
649 }
650
651 String var = "";
652 for (int i = 0; i < length; i++)
653 var += (char) (data[i]);
654 data.cut(-length);
655 if (String::lenUtf8(var.c_str()) < 0)
656 return ParseError;
657 if (!str) {
658 DDebug(s_libName.c_str(),DebugAll,"::decodeUTF8() - Invalid buffer for return data");
659 return InvalidContentsError;
660 }
661 *str = var;
662 #ifdef DEBUG
663 Debug(s_libName.c_str(),DebugAll,"::decodeUtf8() - decoded an UTF8 string value from data='%p', consumed %u bytes",&data,initLen - data.length());
664 #endif
665 return length;
666 }
667
decodeGenTime(DataBlock & data,unsigned int * time,unsigned int * fractions,bool * utc,bool tagCheck)668 int ASNLib::decodeGenTime(DataBlock& data, unsigned int* time, unsigned int* fractions, bool* utc, bool tagCheck)
669 {
670 XDebug(s_libName.c_str(),DebugAll,"::decodeGenTime() from data='%p'",&data);
671 if (data.length() < 2)
672 return InvalidLengthOrTag;
673 #ifdef DEBUG
674 unsigned int initLen = data.length();
675 #endif
676 if (tagCheck) {
677 if (data[0] != GENERALIZED_TIME) {
678 XDebug(s_libName.c_str(),DebugAll,"::decodeGenTime() - Invalid Tag in data='%p'",&data);
679 return InvalidLengthOrTag;
680 }
681 data.cut(-1);
682 }
683 int length = decodeLength(data);
684 if (length < 0) {
685 DDebug(s_libName.c_str(),DebugAll,"::decodeGenTime() - Invalid Length in data='%p'",&data);
686 return length;
687 }
688
689 if ((unsigned int)length > data.length() || length < 14) {
690 DDebug(s_libName.c_str(),DebugAll,"::decodeGenTime() - Invalid Length in data='%p'",&data);
691 return InvalidLengthOrTag;
692 }
693 String date = "";
694 for (int i = 0; i < length; i++)
695 date += (char) (data[i]);
696 data.cut(-length);
697
698 if (!(utc && fractions && time)) {
699 DDebug(s_libName.c_str(),DebugAll,"::decodeGenTime() - Invalid buffer for return data");
700 return InvalidContentsError;
701 }
702
703 unsigned int year, month, day, hours, minutes, seconds;
704 int timeDiff = 0;
705
706 *utc = false;
707 *fractions = 0;
708
709 if (date[date.length() - 1] == 'Z') {
710 *utc = true;
711 date = date.substr(0,date.length() - 1);
712 }
713 else {
714 int pos = date.find('-');
715 if (pos < 0)
716 pos = date.find('+');
717 if (pos >0 && pos != (int)date.length() - 5)
718 return InvalidContentsError;
719 if (pos > 0) {
720 char sign = date.at(pos);
721 unsigned int hDiff = (unsigned int) date.substr(date.length() - 4,2).toInteger(-1,10);
722 if (hDiff > 11)
723 return InvalidContentsError;
724 unsigned int mDiff = (unsigned int) date.substr(date.length() - 2,2).toInteger(-1,10);
725 if (mDiff > 59)
726 return InvalidContentsError;
727 unsigned int diff = Time::toEpoch(1970,1,1,hDiff,mDiff,0);
728 if (sign == '-')
729 timeDiff = diff;
730 else
731 timeDiff -= diff;
732 *utc = true;
733 date = date.substr(0,date.length() - 5);
734 }
735 }
736 ObjList* list = date.split('.');
737 if (!list || list->count() > 2)
738 return InvalidContentsError;
739 if (list->count() == 2)
740 *fractions = (*list)[1]->toString().toInteger(0,10);
741
742 String dateTime = (*list)[0]->toString();
743 TelEngine::destruct(list);
744
745 year = dateTime.substr(0,4).toInteger(-1,10);
746 month = dateTime.substr(4,2).toInteger(-1,10);
747 day = dateTime.substr(6,2).toInteger(-1,10);
748 hours = dateTime.substr(8,2).toInteger(-1,10);
749 minutes = dateTime.substr(10,2).toInteger(-1,10);
750 seconds = dateTime.substr(12,2).toInteger(-1,10);
751 if (year < 1970 || month > 12 || day > 31 || hours > 23 || minutes > 59 || seconds > 59)
752 return InvalidContentsError;
753
754 unsigned int epochTime = Time::toEpoch(year,month,day,hours,minutes,seconds);
755 if (epochTime == (unsigned int) -1)
756 return InvalidContentsError;
757 *time = epochTime + timeDiff;
758 #ifdef DEBUG
759 Debug(s_libName.c_str(),DebugAll,"::decodeGenTime() - decoded time value from data='%p', consumed %u bytes",&data,initLen - data.length());
760 #endif
761 return length;
762 }
763
decodeUTCTime(DataBlock & data,unsigned int * time,bool tagCheck)764 int ASNLib::decodeUTCTime(DataBlock& data, unsigned int* time, bool tagCheck)
765 {
766 XDebug(s_libName.c_str(),DebugAll,"::decodeUTCTime() from data='%p'",&data);
767 if (data.length() < 2)
768 return InvalidLengthOrTag;
769 #ifdef DEBUG
770 unsigned int initLen = data.length();
771 #endif
772 if (tagCheck) {
773 if (data[0] != UTC_TIME) {
774 XDebug(s_libName.c_str(),DebugAll,"::decodeUTCTime() - Invalid Tag in data='%p'",&data);
775 return InvalidLengthOrTag;
776 }
777 data.cut(-1);
778 }
779 int length = decodeLength(data);
780 if (length < 0) {
781 DDebug(s_libName.c_str(),DebugAll,"::decodeUTCTime() - Invalid Length in data='%p'",&data);
782 return length;
783 }
784
785 if ((unsigned int)length > data.length() || length < 11) {
786 DDebug(s_libName.c_str(),DebugAll,"::decodeUTCTime() - Invalid Length in data='%p'",&data);
787 return InvalidLengthOrTag;
788 }
789 String date = "";
790 for (int i = 0; i < length; i++)
791 date += (char) (data[i]);
792 data.cut(-length);
793
794 if (!time) {
795 DDebug(s_libName.c_str(),DebugAll,"::decodeUTCTime() - Invalid buffer for return data");
796 return InvalidContentsError;
797 }
798 unsigned int year = 0, month = 0, day = 0, hours = 0, minutes = 0, seconds = 0;
799 int timeDiff = 0;
800
801 int len = date.length();
802 if (date[date.length() - 1] == 'Z')
803 date = date.substr(0,len - 1);
804 else {
805 int pos = date.find('-');
806 if (pos < 0)
807 pos = date.find('+');
808 if ((pos >0 && pos != len - 5) || pos < 0)
809 return InvalidContentsError;
810 if (pos > 0) {
811 char sign = date.at(pos);
812 unsigned int hDiff = (unsigned int) date.substr(len - 4,2).toInteger(-1,10);
813 if (hDiff > 11)
814 return InvalidContentsError;
815 unsigned int mDiff = (unsigned int) date.substr(len - 2,2).toInteger(-1,10);
816 if (mDiff > 59)
817 return InvalidContentsError;
818 unsigned int diff = Time::toEpoch(1970,1,1,hDiff,mDiff,0);
819 if (sign == '-')
820 timeDiff = diff;
821 else
822 timeDiff -= diff;
823 date = date.substr(0,len - 5);
824 }
825 }
826 year = date.substr(0,2).toInteger(-1,10);
827 year = (year > 50) ? 1900 + year : 2000 + year;
828 month = date.substr(2,2).toInteger(-1,10);
829 day = date.substr(4,2).toInteger(-1,10);
830 hours = date.substr(6,2).toInteger(-1,10);
831 minutes = date.substr(8,2).toInteger(-1,10);
832 if (date.length() > 10)
833 seconds = date.substr(10,2).toInteger(-1,10);
834 if (year < 1970 || month > 12 || day > 31 || hours > 23 || minutes > 59 || seconds > 59)
835 return InvalidContentsError;
836
837 unsigned int epochTime = Time::toEpoch(year,month,day,hours,minutes,seconds);
838 if (epochTime == (unsigned int) -1)
839 return InvalidContentsError;
840 *time = epochTime + timeDiff;
841 #ifdef DEBUG
842 Debug(s_libName.c_str(),DebugAll,"::decodeUTCTime() - decoded time value from data='%p', consumed %u bytes",&data,initLen - data.length());
843 #endif
844 return length;
845 }
846
decodeAny(DataBlock data,DataBlock * val,bool tagCheck)847 int ASNLib::decodeAny(DataBlock data, DataBlock* val, bool tagCheck)
848 {
849 XDebug(s_libName.c_str(),DebugAll,"::decodeAny() from data='%p'",&data);
850 if (!val) {
851 DDebug(s_libName.c_str(),DebugAll,"::decodeAny() - Invalid buffer for return data");
852 return InvalidContentsError;
853 }
854 val->append(data);
855 return data.length();
856 }
857
decodeSequence(DataBlock & data,bool tagCheck)858 int ASNLib::decodeSequence(DataBlock& data, bool tagCheck)
859 {
860 XDebug(s_libName.c_str(),DebugAll,"::decodeSequence() from data='%p'",&data);
861 if (data.length() < 2)
862 return InvalidLengthOrTag;
863 #ifdef DEBUG
864 unsigned int initLen = data.length();
865 #endif
866 if (tagCheck) {
867 if (data[0] != SEQUENCE) {
868 DDebug(s_libName.c_str(),DebugAll,"::decodeSequence() - Invalid Tag in data='%p'",&data);
869 return InvalidLengthOrTag;
870 }
871 data.cut(-1);
872 }
873 int length = decodeLength(data);
874 if (length < 0)
875 Debug(s_libName.c_str(),DebugAll,"::decodeSequence() - Invalid Length in data='%p'",&data);
876 #ifdef DEBUG
877 Debug(s_libName.c_str(),DebugAll,"::decodeSequence() - decoded sequence tags from data='%p', consumed %u bytes",&data,initLen - data.length());
878 #endif
879 return length;
880 }
881
decodeSet(DataBlock & data,bool tagCheck)882 int ASNLib::decodeSet(DataBlock& data, bool tagCheck)
883 {
884 XDebug(s_libName.c_str(),DebugAll,"::decodeSet() from data='%p",&data);
885 if (data.length() < 2)
886 return InvalidLengthOrTag;
887 #ifdef DEBUG
888 unsigned int initLen = data.length();
889 #endif
890 if (tagCheck) {
891 if (data[0] != SET) {
892 DDebug(s_libName.c_str(),DebugAll,"::decodeSet() - Invalid Tag in data='%p'",&data);
893 return InvalidLengthOrTag;
894 }
895 data.cut(-1);
896 }
897 int length = decodeLength(data);
898 #ifdef DEBUG
899 if (length < 0)
900 Debug(s_libName.c_str(),DebugAll,"::decodeSet() - Invalid Length in data='%p'",&data);
901 else
902 Debug(s_libName.c_str(),DebugAll,"::decodeSet() - decoded set tags from data='%p', consumed %u bytes",&data,initLen - data.length());
903 #endif
904 return length;
905 }
906
encodeBoolean(bool val,bool tagCheck)907 DataBlock ASNLib::encodeBoolean(bool val, bool tagCheck)
908 {
909 /**
910 * ASN.1 boolean ::= 0x01 asnlength=0x01 byte
911 */
912 DataBlock data;
913 uint8_t b = BOOLEAN;
914 if (tagCheck) {
915 data.append(&b, 1);
916 b = 1;
917 data.append(&b, 1);
918 }
919 b = val ? 1 : 0;
920 data.append(&b, 1);
921 XDebug(s_libName.c_str(),DebugAll,"::encodeBoolean('%s') - encoded boolean value into %u bytes",String::boolText(val),data.length());
922 return data;
923 }
924
encodeInteger(u_int64_t intVal,bool tagCheck)925 DataBlock ASNLib::encodeInteger(u_int64_t intVal, bool tagCheck)
926 {
927 /**
928 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
929 */
930 DataBlock data;
931 uint8_t tag = INTEGER;
932
933 // 9 consecutive ones or zeros are not allowed at the beginning of an integer
934 int size = sizeof(u_int64_t);
935 uint16_t msb = (uint16_t)(intVal >> ((size - 1) * 8 - 1));
936
937 while (((msb & 0x1FF) == 0 || (msb & 0x1FF) == 0x1FF) && (size - 1 >= 1)) {
938 size--;
939 msb = (uint16_t)(intVal >> ((size - 1) * 8 - 1));
940 }
941 if (size == 0)
942 return data;
943
944 DataBlock contents;
945 while(size) {
946 uint8_t byte = (uint8_t)(intVal >> ((size - 1) * 8));
947 contents.append(&byte, 1);
948 size--;
949 }
950
951 if (contents.length() == 0)
952 return data;
953 if (tagCheck) {
954 data.append(&tag, 1);
955 DataBlock len = buildLength(contents);
956 data.append(len);
957 }
958 data.append(contents);
959 XDebug(s_libName.c_str(),DebugAll,"::encodeInteger('" FMT64 "') - encoded into %u bytes",intVal,data.length());
960 return data;
961 }
962
encodeBitString(String val,bool tagCheck)963 DataBlock ASNLib::encodeBitString(String val, bool tagCheck)
964 {
965 /**
966 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
967 */
968 DataBlock data;
969 uint8_t tag = BIT_STRING;
970 DataBlock contents;
971
972 int l = val.length();
973 uint8_t trail = (-l) & 0x07;
974 for (int i = 0; i < trail; i++)
975 val += "0";
976 contents.append(&trail, 1);
977
978 for (unsigned int i = 0; i < val.length(); i += 8) {
979 uint8_t hex = val.substr(i, 8).toInteger(0,2);
980 contents.append(&hex, 1);
981 }
982
983 if (tagCheck) {
984 data.append(&tag,1);
985 DataBlock len = buildLength(contents);
986 data.append(len);
987 }
988 data.append(contents);
989 XDebug(s_libName.c_str(),DebugAll,"::encodeBitString('%s') - encoded bit string into %u bytes",val.c_str(),data.length());
990 return data;
991 }
992
encodeOctetString(OctetString strVal,bool tagCheck)993 DataBlock ASNLib::encodeOctetString(OctetString strVal, bool tagCheck)
994 {
995 /**
996 * ASN.1 octet string ::= 0x04 asnlength byte {byte}*
997 */
998 DataBlock data;
999 uint8_t tag = OCTET_STRING;
1000 if (tagCheck) {
1001 data.append(&tag, 1);
1002 DataBlock len = buildLength(strVal);
1003 data.append(len);
1004 }
1005 data.append(strVal);
1006 XDebug(s_libName.c_str(),DebugAll,"ASNLib::encodeOctetString('%s') - encoded octet string into %u bytes",
1007 strVal.toHexString().c_str(),data.length());
1008 return data;
1009 }
1010
encodeNull(bool tagCheck)1011 DataBlock ASNLib::encodeNull(bool tagCheck)
1012 {
1013 /**
1014 * ASN.1 null ::= 0x05 00
1015 */
1016 XDebug(s_libName.c_str(),DebugAll,"::encodeNull()");
1017 DataBlock data;
1018 uint8_t tag = NULL_ID;
1019 if (tagCheck) {
1020 data.append(&tag, 1);
1021 tag = 0;
1022 data.append(&tag, 1);
1023 }
1024 return data;
1025 }
1026
encodeOID(ASNObjId obj,bool tagCheck)1027 DataBlock ASNLib::encodeOID(ASNObjId obj, bool tagCheck)
1028 {
1029 /**
1030 * ASN.1 object id ::= 0x06 asnlength byte {byte}*
1031 */
1032 DataBlock data;
1033 uint8_t tag = OBJECT_ID;
1034
1035 DataBlock cont = obj.getIds();
1036 DataBlock contents;
1037
1038 if (cont.length() == 0)
1039 return data;
1040
1041 // first byte is built following the rule first = 40 * x + y
1042 // x must not be greater than 2 (joint-iso-ccitt identifier)
1043 if (cont[0] > 2) {
1044 Debug(s_libName.c_str(),DebugAll,"::encodeOID('%s') - first identifier is greater than the maximum allowed identifier 'joint-iso-ccitt'(2)",
1045 obj.toString().c_str());
1046 return data;
1047 }
1048 uint8_t first = 40 * cont[0];
1049 if (cont.length() > 1) {
1050 // y must not be greater than 39 if x < 2
1051 if (cont[0] < 2 && cont[1] > 39) {
1052 Debug(s_libName.c_str(),DebugAll,"::encodeOID('%s') - cannot encode second identifier, its value is not allowed for the first identifier",
1053 obj.toString().c_str());
1054 return data;
1055 }
1056 first += cont[1];
1057 cont.cut(-1);
1058 }
1059 contents.append(&first, 1);
1060 cont.cut(-1);
1061
1062 contents.append(cont);
1063 if (tagCheck) {
1064 data.append(&tag,1);
1065 DataBlock len = buildLength(contents);
1066 data.append(len);
1067 }
1068 data.append(contents);
1069 XDebug(s_libName.c_str(),DebugAll,"::encodeOID('%s') - encoded object ID into %u bytes",obj.toString().c_str(),data.length());
1070 return data;
1071 }
1072
encodeReal(float val,bool tagCheck)1073 DataBlock ASNLib::encodeReal(float val, bool tagCheck)
1074 {
1075 Debug(s_libName.c_str(),DebugInfo,"::encodeReal() - STUB: encoding for real values not implemented");
1076 DataBlock data;
1077 return data;
1078 }
1079
encodeString(String str,int type,bool tagCheck)1080 DataBlock ASNLib::encodeString(String str, int type, bool tagCheck)
1081 {
1082 DataBlock data;
1083 uint8_t tag = type;
1084
1085 DataBlock contents;
1086 if (type == NUMERIC_STR ||
1087 type == PRINTABLE_STR ||
1088 type == IA5_STR ||
1089 type == VISIBLE_STR )
1090 contents.append(str);
1091
1092 if (contents.length() == 0)
1093 return data;
1094
1095 if (tagCheck) {
1096 data.append(&tag, 1);
1097 DataBlock len = buildLength(contents);
1098 data.append(len);
1099 }
1100 data.append(contents);
1101 XDebug(s_libName.c_str(),DebugAll,"::encodeString() - encoded string into %u bytes",data.length());
1102 return data;
1103 }
1104
encodeUtf8(String str,bool tagCheck)1105 DataBlock ASNLib::encodeUtf8(String str, bool tagCheck)
1106 {
1107 DDebug(s_libName.c_str(),DebugAll,"::encodeUtf8()");
1108 DataBlock data;
1109 uint8_t tag = UTF8_STR;
1110 DataBlock contents;
1111 contents.append(str);
1112 if (tagCheck) {
1113 data.append(&tag, 1);
1114 DataBlock len = buildLength(contents);
1115 data.append(len);
1116 }
1117 data.append(contents);
1118 XDebug(s_libName.c_str(),DebugAll,"::encodeString() - encoded UTF8 string into %u bytes",data.length());
1119 return data;
1120 }
1121
encodeGenTime(unsigned int time,unsigned int fractions,bool tagCheck)1122 DataBlock ASNLib::encodeGenTime(unsigned int time, unsigned int fractions, bool tagCheck)
1123 {
1124 DataBlock data;
1125 uint8_t tag = GENERALIZED_TIME;
1126
1127 int year;
1128 unsigned int month, day, hours, minutes, seconds;
1129 if (!Time::toDateTime(time, year, month, day, hours, minutes, seconds))
1130 return data;
1131 String dateTime = "";
1132 dateTime += year;
1133 (month < 10) ? dateTime += 0 : "";
1134 dateTime += month;
1135 (day < 10) ? dateTime += 0 : "";
1136 dateTime += day;
1137 (hours < 10) ? dateTime += 0 : "";
1138 dateTime += hours;
1139 (minutes < 10) ? dateTime += 0 : "";
1140 dateTime += minutes;
1141 (seconds < 10) ? dateTime += 0 : "";
1142 dateTime += seconds;
1143 if (fractions != 0) {
1144 dateTime += ".";
1145 dateTime += fractions;
1146 }
1147 dateTime += 'Z';
1148 DataBlock contents;
1149 contents.append(dateTime);
1150 if (tagCheck) {
1151 data.append(&tag, 1);
1152 DataBlock len = buildLength(contents);
1153 data.append(len);
1154 }
1155 data.append(contents);
1156 XDebug(s_libName.c_str(),DebugAll,"::encodeGenTime(time='%u', fractions='%u') - encoded time value into %u bytes",time,fractions,data.length());
1157 return data;
1158 }
1159
encodeUTCTime(unsigned int time,bool tagCheck)1160 DataBlock ASNLib::encodeUTCTime(unsigned int time, bool tagCheck)
1161 {
1162 DataBlock data;
1163 uint8_t tag = UTC_TIME;
1164
1165 int year;
1166 unsigned int month, day, hours, minutes, seconds;
1167 if (!Time::toDateTime(time, year, month, day, hours, minutes, seconds))
1168 return data;
1169 String dateTime = "";
1170 (year % 100 < 10) ? dateTime += 0 : "";
1171 dateTime += (year % 100);
1172 (month < 10) ? dateTime += 0 : "";
1173 dateTime += month;
1174 (day < 10) ? dateTime += 0 : "";
1175 dateTime += day;
1176 (hours < 10) ? dateTime += 0 : "";
1177 dateTime += hours;
1178 (minutes < 10) ? dateTime += 0 : "";
1179 dateTime += minutes;
1180 (seconds < 10) ? dateTime += 0 : "";
1181 dateTime += seconds;
1182
1183 dateTime += 'Z';
1184
1185 DataBlock contents;
1186 contents.append(dateTime);
1187 if (tagCheck) {
1188 data.append(&tag, 1);
1189 DataBlock len = buildLength(contents);
1190 data.append(len);
1191 }
1192 data.append(contents);
1193 XDebug(s_libName.c_str(),DebugAll,"::encodeUTCTime(time='%u') - encoded time value into %u bytes",time,data.length());
1194 return data;
1195 }
1196
encodeAny(DataBlock data,bool tagCheck)1197 DataBlock ASNLib::encodeAny(DataBlock data, bool tagCheck)
1198 {
1199 XDebug(s_libName.c_str(),DebugAll,"::encodeAny()");
1200 DataBlock db;
1201 db.append(data);
1202 return db;
1203 }
1204
encodeSequence(DataBlock & data,bool tagCheck)1205 int ASNLib::encodeSequence(DataBlock& data, bool tagCheck)
1206 {
1207 DataBlock len;
1208 if (tagCheck) {
1209 len = buildLength(data);
1210 data.insert(len);
1211 DataBlock db;
1212 u_int8_t tag = SEQUENCE;
1213 db.append(&tag, 1);
1214 data.insert(db);
1215 }
1216 XDebug(s_libName.c_str(),DebugAll,"::encodeSequence() - added sequence tag and length for a block of %d bytes",data.length());
1217 return len.length();
1218 }
1219
encodeSet(DataBlock & data,bool tagCheck)1220 int ASNLib::encodeSet(DataBlock& data, bool tagCheck)
1221 {
1222 DDebug(s_libName.c_str(),DebugAll,"::encodeSet()");
1223 DataBlock len;
1224 if (tagCheck) {
1225 len = buildLength(data);
1226 data.insert(len);
1227 DataBlock db;
1228 u_int8_t tag = SET;
1229 db.append(&tag, 1);
1230 data.insert(db);
1231 }
1232 XDebug(s_libName.c_str(),DebugAll,"::encodeSet() - added set tag and length for a block of %d bytes",data.length());
1233 return len.length();
1234 }
1235
1236 /**
1237 * AsnTag
1238 */
decode(AsnTag & tag,DataBlock & data)1239 void AsnTag::decode(AsnTag& tag, DataBlock& data)
1240 {
1241 XDebug(s_libName.c_str(),DebugAll,"AsnTag::decode()");
1242 tag.classType((Class)(data[0] & 0xc0));
1243 tag.type((Type)(data[0] & 0x20));
1244
1245 unsigned int code = 0;
1246 code |= data[0] & 0x1f;
1247 unsigned int len = 1;
1248 if (IS_EXTENSION_ID(code) && data.length() >= 2) { // extended tag
1249 code = 0;
1250 while (len < data.length() && (data[len] & ASN_BIT8) == ASN_BIT8) {
1251 code = code << 8;
1252 code |= (data[len] & 0x7f);
1253 len++;
1254 }
1255 code |= data[len] & 0x7f;
1256 }
1257 tag.code(code);
1258 tag.encode();
1259 }
1260
encode(Class clas,Type type,unsigned int code,DataBlock & data)1261 void AsnTag::encode(Class clas, Type type, unsigned int code, DataBlock& data)
1262 {
1263 XDebug(s_libName.c_str(),DebugAll,"AsnTag::encode(clas=0x%x, type=0x%x, code=%u)",clas,type,code);
1264 if (code < 31) {
1265 u_int8_t tag = clas | type | code;
1266 data.insert(DataBlock(&tag,sizeof(tag)));
1267 }
1268 else {
1269 u_int8_t last = clas | type | 31;
1270 DataBlock coding;
1271 coding.append(&last,sizeof(last));
1272 int size = sizeof(unsigned int);
1273 bool start = false;
1274 while (size > 1) {
1275 u_int8_t msb = (code >> ((size - 1) * 8));
1276 if (start) {
1277 msb |= 0x80;
1278 coding.append(&msb,sizeof(msb));
1279 }
1280 else {
1281 if (msb == 0) {
1282 size--;
1283 continue;
1284 }
1285 else {
1286 start = true;
1287 msb |= 0x80;
1288 coding.append(&msb,sizeof(msb));
1289 }
1290 }
1291 size--;
1292 }
1293 last = code;
1294 coding.append(&last,sizeof(last));
1295 data.insert(coding);
1296 }
1297 #ifdef XDEBUG
1298 String str;
1299 str.hexify(data.data(),data.length(),' ');
1300 Debug(s_libName.c_str(),DebugAll,"AsnTag::encode(clas=0x%x, type=0x%x, code=%u) tag=%s",clas,type,code,str.c_str());
1301 #endif
1302 }
1303
1304 /**
1305 * ASNObjId
1306 */
ASNObjId()1307 ASNObjId::ASNObjId()
1308 {
1309 }
1310
ASNObjId(const String & val)1311 ASNObjId::ASNObjId(const String& val)
1312 : m_value(val)
1313 {
1314 DDebug(s_libName.c_str(),DebugAll,"ASNObjId('%s') created",val.c_str());
1315 }
1316
ASNObjId(const String & name,const String & val)1317 ASNObjId::ASNObjId(const String& name, const String& val)
1318 : m_value(val), m_name(name)
1319 {
1320 DDebug(s_libName.c_str(),DebugAll,"ASNObjId('%s', '%s') created",name.c_str(),val.c_str());
1321 }
1322
ASNObjId(AsnMib * mib)1323 ASNObjId::ASNObjId(AsnMib* mib)
1324 {
1325 DDebug(s_libName.c_str(),DebugAll,"ASNObjId() created from AsnMib [%p]",mib);
1326 if (mib) {
1327 m_name = mib->getName();
1328 m_value = mib->getOID();
1329 }
1330 }
1331
~ASNObjId()1332 ASNObjId::~ASNObjId()
1333 {
1334 m_ids.clear();
1335 }
1336
toDataBlock()1337 void ASNObjId::toDataBlock()
1338 {
1339 DDebug(s_libName.c_str(),DebugAll,"ASNObjId::toDataBlock() '%s'", m_value.c_str());
1340 m_ids.clear();
1341 ObjList* list = m_value.split('.',false);
1342 if (list) {
1343 for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
1344 String* s = static_cast<String*>(o->get());
1345 int val = s->toInteger();
1346 if (val < 128)
1347 m_ids.append(&val, 1);
1348 else {
1349 DataBlock db;
1350 int size = sizeof(int);
1351 uint8_t v = val;
1352 v = v & 0x7f;
1353 db.append(&v,1);
1354 size--;
1355 val = val >> 7;
1356 while (val != 0) {
1357 v = val;
1358 v = v & 0x7f;
1359 v = v | 0x80;
1360 DataBlock tmp;
1361 tmp.append(&v,1);
1362 db.insert(tmp);
1363 size--;
1364 val = val >> 7;
1365 }
1366 m_ids.append(db);
1367 }
1368 }
1369 TelEngine::destruct(list);
1370 }
1371 }
1372
getIds()1373 DataBlock ASNObjId::getIds()
1374 {
1375 toDataBlock();
1376 return m_ids;
1377 }
1378
1379 /**
1380 * AsnMib
1381 */
1382 TokenDict AsnMib::s_access[] = {
1383 {"accessible-for-notify", AsnMib::accessibleForNotify},
1384 {"read-only", AsnMib::readOnly},
1385 {"read-write", AsnMib::readWrite},
1386 {"read-create", AsnMib::readCreate},
1387 {0,0}
1388 };
1389
AsnMib(NamedList & params)1390 AsnMib::AsnMib(NamedList& params)
1391 {
1392 if (!params)
1393 return;
1394 m_index = 0;
1395 m_oid = params;
1396 m_name = params.getValue("name","");
1397 m_access = params.getValue("access","");
1398 m_accessVal = lookup(m_access,s_access,0);
1399 m_type = params.getValue("type","");
1400 m_revision = params.getValue("revision","");
1401 XDebug(s_libName.c_str(),DebugAll,"new AsnMib created with oid : '%s', access : '%s', type : '%s'",
1402 m_oid.c_str(),m_access.c_str(),m_type.c_str());
1403 }
1404
compareTo(AsnMib * mib)1405 int AsnMib::compareTo(AsnMib* mib)
1406 {
1407 if (!mib)
1408 return 1;
1409 DDebug(s_libName,DebugInfo,"AsnMib::compareTo('%s'='%s' [%p]) this=%s[%s] [%p]",
1410 mib->getName().c_str(),mib->toString().c_str(),mib,getName().c_str(),toString().c_str(),this);
1411
1412 // they're equal
1413 if (toString() == mib->toString())
1414 return 0;
1415
1416 ObjList* myIDs = toString().split('.',false);
1417 ObjList* mibIDs = mib->toString().split('.',false);
1418
1419 ObjList* o1 = myIDs->skipNull();
1420 ObjList* o2 = mibIDs->skipNull();
1421 while (o1 && o2) {
1422 String* str1 = static_cast<String*>(o1->get());
1423 o1 = o1->skipNext();
1424 String* str2 = static_cast<String*>(o2->get());
1425 o2 = o2->skipNext();
1426 int diff = str1->toInteger() - str2->toInteger();
1427 if (diff == 0)
1428 continue;
1429 if (diff > 0) {
1430 TelEngine::destruct(myIDs);
1431 TelEngine::destruct(mibIDs);
1432 return 1;
1433 }
1434 if (diff < 0) {
1435 TelEngine::destruct(myIDs);
1436 TelEngine::destruct(mibIDs);
1437 return -1;
1438 }
1439 }
1440
1441 int retValue = 0;
1442 if (!o1)
1443 retValue = -1;
1444 else if (!o2)
1445 retValue = 1;
1446 TelEngine::destruct(myIDs);
1447 TelEngine::destruct(mibIDs);
1448 return retValue;
1449 }
1450
1451 /* vi: set ts=8 sw=4 sts=4 noet: */
1452