// ASN.1 related methods void Person::serialize(ENetPacket* buf) { ASNPerson p; p.name = name.c_str(); p.age = age; AsnBuf abuf; const size_t dataSize = 1024; char data[dataSize]; size_t encodedLen; abuf.Init (data, dataSize); abuf.ResetInWriteRvsMode(); AsnLen len = p.BEncPdu ( abuf, encodedLen ); #ifndef ASN_USE_FILE ofstream outputFile; outputFile.open ("pr.ber"); abuf.ResetInReadMode(); for (; encodedLen > 0; encodedLen--) outputFile.put (abuf.GetByte()); #else # error "Char Asn Encoding not implemented" #endif }
// FUNCTION: BEnc() // PUPROSE: Encode ANY DEFINED BY if "value" is present otherwise encode ANY if // anyBuf is present. If neither is present an exception is thrown. // AsnLen AsnAny::BEnc (AsnBuf &b) const { FUNC("AsnAny::BEnc()"); if (value != NULL) return value->BEnc(b); else if (anyBuf != NULL) { anyBuf->ResetMode(); b.insert(*anyBuf); return anyBuf->length(); #ifdef OLD std::string data; // PIERCE: make this more efficient // anyBuf->ResetMode(); anyBuf->GetSeg(data); anyBuf->ResetMode(); b.PutSegRvs(data.data(), data.length()); return anyBuf->length(); #endif } else throw EXCEPT("Unknown any with no value", ENCODE_ERROR); }
void checkBuf(AsnBuf &b) { Deck::const_iterator i; for (i = b.deck().begin(); i != b.deck().end(); i++) { Card *tmpCard = *i; } }
void bittests(void) { std::cout << "*** Start of AsnBits tests ***\n"; for (int index=0; gBitTestTable[index].input != NULL; index++) { AsnBits asnBits(gBitTestTable[index].input); asnBits.UseNamedBitListRules(gBitTestTable[index].nblFlag); AsnBuf expectedResult(&gBitTestTable[index].result[0], DecTagLen((unsigned char *)gBitTestTable[index].result+1) + 2); AsnBuf result; AsnLen bytesEncoded; std::cout << "AsnBits test " << index << " matches expected result? "; try { asnBits.BEnc(result); if (!(result == expectedResult)) { std::string str; int i; int ch; std::cout << "NO!\n"; std::cout << "FAILED!\n"; std::cout << "Expected Result: "; expectedResult.hexDump(std::cout); std::cout << "\n"; std::cout << "\nActual Result: "; result.hexDump(std::cout); std::cout << "\n"; } else { std::cout << "YES!\n"; } } catch (SnaccException &e) { std::cout << "Encode FAILED: \n"; std::cout << "Error: " << e.what() << std::endl; std::cout << "Stack:\n"; e.getCallStack(std::cout); } } std::cout << "*** End of AsnBits tests ***\n"; }
bool AsnBuf::operator<(const AsnBuf &rhs) const { bool lessThan = true; bool firstTime = true; ResetMode(); rhs.ResetMode(); std::streambuf::int_type ch1; std::streambuf::int_type ch2; while ( lessThan ) { try { ch1 = GetUByte(); } catch (BufferException &) { ch1 = EOF; } try { ch2 = rhs.GetUByte(); } catch (BufferException &) { ch2 = EOF; } if ((ch1 == EOF) && (ch2 == EOF)) { if (firstTime) lessThan = false; break; } else if (ch2 == EOF) { lessThan = false; break; } else if (ch1 == EOF) { break; } if (ch1 > ch2) lessThan = false; else if (ch1 < ch2) break; firstTime = false; } ResetMode(); rhs.ResetMode(); return lessThan; }
void TestSetSorting(void) { int i = 0; while (gSetSortingTable[i].input != NULL) { AsnLen bytesDecoded=0, bytesEncoded; //TestSetSorting1 testSetSorting1; int ch; std::string input, result; hex2str(gSetSortingTable[i].input, input); hex2str(gSetSortingTable[i].derSorted, result); std::stringstream ssInput(input); std::stringstream ssResult(result); AsnBuf inputBuf(ssInput); AsnBuf expectedResultBuf(ssResult); AsnBuf outputBuf; inputBuf.ResetMode(); expectedResultBuf.ResetMode(); gSetSortingTable[i].asnType->BDec(inputBuf, bytesDecoded); bytesEncoded = gSetSortingTable[i].asnType->BEnc(outputBuf); if (bytesEncoded != bytesDecoded) { std::cout << "Encoded / Decode byte length mismatch!!!\n"; } if (outputBuf == expectedResultBuf) { std::cout << "SET sorting SUCCESS!\n"; } else { std::cout << "SET sorting FAILURE!\n"; std::string str; std::cout << "Expected result: "; expectedResultBuf.hexDump(std::cout); std::cout << std::endl; std::cout << "Actual result : "; outputBuf.ResetMode(); outputBuf.hexDump(std::cout); std::cout << std::endl; } i++; } multiCardSetTest(); }
void Person::deserialize(ENetPacket* buf) { #ifndef ASN_USE_FILE // open the data file ifstream dataFile; dataFile.open ("pr.ber"); // get size of the data file file dataFile.seekg (0, ios::end); int dataSize = dataFile.tellg(); dataFile.seekg (0); // read data from file into contiguous block for a buffer char data[dataSize]; dataFile.read (data, dataSize); dataFile.close(); // // put the BER data read from the file // into buffer format, ready for reading from the // beginning // AsnBuf inputBuf; inputBuf.InstallData ((char*)data, dataSize); size_t decodedLen; ASNPerson p; if (!p.BDecPdu (inputBuf, decodedLen)) { std::cerr << "ERROR - Decode routines failed, exiting..." << endl; exit (1); } #else # error "Char Asn Decoding not implemented" #endif /* ASNPerson p; const size_t dataSize = 10; char data[dataSize]; size_t decodedLen; //buf.Init (data, dataSize); buf.ResetInReadMode(); if (!p.BDecPdu ( buf, decodedLen )) { std::cerr << "Failed to decode Asn.1"<< std::endl; exit (1); } */ }
/* any's and these are the ONLY any's that should call this function. */ void AsnAny::BDecContent (const AsnBuf &b, AsnTag tag, AsnLen len, AsnLen &bytesDecoded) { long lBytesToUnget = 0; lBytesToUnget += BytesInLen(len); lBytesToUnget += BytesInTag(tag); b.UnGetBytes(lBytesToUnget); anyBuf = new AsnBuf; b.GrabAny(*anyBuf, bytesDecoded); }
void multiCardSetTest() { OctetStringSetOf octsSet; unsigned char test[10213]; fillTestBuffer(test,10213); octsSet.insert(octsSet.end(), SNACC::AsnOcts())->Set((char*)test, 10213); std::cout << "**** LARGE SET OF OCTET STRING TEST ****\n"; AsnBuf tmpBuf; AsnLen bytesEncoded = octsSet.BEnc(tmpBuf); checkBuf(tmpBuf); AsnLen bytesDecoded = 0; std::stringstream ss; ss << tmpBuf; OctetStringSetOf octsSet2; tmpBuf.ResetMode(); octsSet2.BDec(tmpBuf, bytesDecoded); if (bytesEncoded != bytesDecoded) { std::cout << "Bytes encoded/decoded do not match\n"; } if (checkTestBuffer(octsSet2.front().c_ustr(), octsSet2.front().Len())) { std::cout << "SUCCESS!\n"; } else { std::cout << "FAILURE!\n"; } std::cout << "**** END OF LARGE SET OF OCTET STRING TEST ****\n"; }
// Decodes a BER BIT STRING from the given buffer and stores // the value in this object. void AsnBits::BDecContent (const AsnBuf &b, AsnTag tagId, AsnLen elmtLen, AsnLen &bytesDecoded) { FUNC("AsnBits::BDecContent"); if (elmtLen == INDEFINITE_LEN || elmtLen > b.length()) { throw MemoryException(elmtLen, "elmtLen requests for too much data", STACK_ENTRY); } /* * tagId is encoded tag shifted into long int. * if CONS bit is set then constructed bit string */ if (tagId & 0x20000000) BDecConsBits (b, elmtLen, bytesDecoded); else /* primitive octet string */ { if (elmtLen == INDEFINITE_LEN) throw BoundsException("indefinite length on primitive", STACK_ENTRY); if (elmtLen > b.length() || elmtLen <= 0) throw BoundsException("length problem on decoding content", STACK_ENTRY); bytesDecoded += elmtLen; elmtLen--; unsigned int iUnusedBitLen= (unsigned int)b.GetByte(); if (iUnusedBitLen > 7) throw BoundsException("Length problem - Unused bits > 7", STACK_ENTRY); bitLen = (elmtLen * 8) - iUnusedBitLen; bits = new unsigned char[elmtLen]; b.GetUSeg (bits, elmtLen); } } /* AsnBits::BDecContent */
bool AsnBuf::operator == (const AsnBuf &b) const { bool equal = true; ResetMode(); b.ResetMode(); std::streambuf::int_type ch1; std::streambuf::int_type ch2; while ( equal ) { try { ch1 = GetUByte(); } catch (BufferException &) { ch1 = EOF; } try { ch2 = b.GetUByte(); } catch (BufferException &) { ch2 = EOF; } if ((ch1 == EOF) && (ch1 == EOF)) break; if (ch1 != ch2) equal = false; } ResetMode(); b.ResetMode(); return equal; }
// insert() // // insert cards from b into this AsnBuf // // TBD: is it necessary to return the length? // long AsnBuf::splice(AsnBuf &b) { if (m_card != m_deck.end() && ((*m_card == NULL) || (*m_card)->length() == 0)) { delete *m_card; m_card = m_deck.erase(m_card); } long length = b.length(); Deck::reverse_iterator ib; for (ib = b.m_deck.rbegin(); ib != b.m_deck.rend(); ++ib) { m_card = m_deck.insert(m_deck.begin(), *ib); } b.m_deck.clear(); return length; }
// FUNCTION: BEnc() // PUPROSE: Encode ANY DEFINED BY if "value" is present otherwise encode ANY if // anyBuf is present. If neither is present an exception is thrown. // AsnLen AsnAny::BEnc (AsnBuf &b) const { FUNC("AsnAny::BEnc()"); if (value != NULL) return value->BEnc(b); else if (anyBuf != NULL) { anyBuf->ResetMode(); b.insert(*anyBuf); return anyBuf->length(); } else throw EXCEPT("Unknown any with no value", ENCODE_ERROR); }
// insert() // // insert cards from b into this AsnBuf // // TBD: is it necessary to return the length? // long AsnBuf::splice(AsnBuf &b) { Deck::iterator ib = b.m_deck.end(); //#ifdef _DEBUG // Card *tmpCard = *ib; //#endif long length = b.length(); if (m_card != m_deck.end() && (*m_card)->length() == 0) m_card = m_deck.erase(m_card); do { ib--; //#ifdef _DEBUG // tmpCard = *ib; //#endif m_card = m_deck.insert(m_deck.begin(), *ib); ib = b.m_deck.erase(ib); } while (ib != b.m_deck.begin()) ; return length; }
// BDec() // // Decoded ANY DEFINED BY or UNKNOWN ANY from 'b'. If an ANY DEFINED // BY is found it's will be decoded into value. If an UNKNOWN ANY is // found it's binary values will be copied into 'anyBuf'. // void AsnAny::BDec (const AsnBuf &b, AsnLen &bytesDecoded) { FUNC("AsnAny::BDec"); // ai will be NULL if this is an ANY (not an ANY DEFINED BY) if (ai == NULL) { anyBuf = new AsnBuf; b.GrabAny(*anyBuf, bytesDecoded); } else { // the type is already known clone it and use it's BDec to decode the // ASN.1 // value = ai->typeToClone->Clone(); if (value == NULL) { throw SnaccException(STACK_ENTRY, "typeToClone->Clone() failed", INVALID_ANY); } else value->BDec (b, bytesDecoded); } }
main (int argc, char *argv[]) { AsnBuf inputBuf; AsnBuf outputBuf; size_t encodedLen; size_t decodedLen; size_t dataSize; ifstream dataFile; PersonnelRecord pr; if (argc != 2) { cerr << "Usage: " << argv[0] << " <BER data file name>" << endl; cerr << " Decodes the given PersonnelRecord BER data file" << endl; cerr << " and re-encodes it to stdout" << endl; exit (1); } // open the data file dataFile.open (argv[1]); if (!dataFile) { perror ("ifstream::open"); exit (1); } // get size of the data file file dataFile.seekg (0, ios::end); dataSize = dataFile.tellg(); dataFile.seekg (0); // read data from file into contiguous block for a buffer #if HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS char data[dataSize]; #else char *data = new char[dataSize]; if (!data) return 1; #endif /* HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS */ dataFile.read (data, dataSize); dataFile.close(); // // put the BER data read from the file // into buffer format, ready for reading from the // beginning // inputBuf.InstallData (data, dataSize); if (!pr.BDecPdu (inputBuf, decodedLen)) { cerr << "--- ERROR - Decode routines failed, exiting..." << endl; exit (1); } cerr << "decodedValue PersonnelRecord ::= " << pr << endl << endl; // // allocate a new buffer set up for writing to // #if HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS char outputData[dataSize + 512]; #else char *outputData = new char[dataSize + 512]; if (!outputData) return 1; #endif /* HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS */ outputBuf.Init (outputData, dataSize+512); outputBuf.ResetInWriteRvsMode(); if (!pr.BEncPdu (outputBuf, encodedLen)) { cerr << "--- ERROR - Encode routines failed" << endl; } // write the BER value to cout outputBuf.ResetInReadMode(); for (; encodedLen > 0; encodedLen--) cout.put (outputBuf.GetByte()); return 0; }
// Encodes the content (included unused bits octet) of the BIT STRING // to the given buffer. AsnLen AsnBits::BEncContent (AsnBuf &b) const { size_t unusedBits; size_t byteLen; unsigned int i; //bool bStop; // IF bitstring is a NamedBitList if (nblFlag) { // Calculate last octet. // size_t finalOctet; if (bitLen <= 8) finalOctet = 0; else if (bitLen % 8 == 0) finalOctet = ((bitLen / 8) - 1); else finalOctet = bitLen / 8; // The final octet is the last octet which has at least // one bit set. Loop backwards starting with the // last octet (calculated above) until you find an // that has at least one bit set (it's value is not 0). // if (bits != NULL) for (; finalOctet > 0 && bits[finalOctet] == 0; finalOctet--); // Calculate unsigned bits in final octet // if (bits == NULL || (finalOctet == 0 && bits[0] == 0)) { byteLen = 0; unusedBits = 0; } else { // Calculate how many trailing bits are unset in the // last octet. unusedBits=0; for (i = 0; i < 8 && ! (bits[finalOctet] & (0x01 << i)); i++) unusedBits++; byteLen = finalOctet + 1; } } else { // If this is not a NamedBitList Calculate the unusedBits // as ( (BitLen() / 8) + 1) * 8 ) - BitLen(); // // In other words it's the number of bits not used by // the BIT STRING specification, not the number of unset // bits in the the final subsequent octet. unusedBits = bitLen % 8; if (unusedBits != 0) unusedBits = 8 - unusedBits; byteLen = (bitLen+7)/8; } b.PutSegRvs (bits, byteLen); // unusedBits = (bitLen % 8); // if (unusedBits != 0) // unusedBits = 8 - unusedBits; b.PutByteRvs ((unsigned char)unusedBits); return byteLen + 1; } /* AsnBits::BEncContent */
main (int argc, char *argv[]) { ofstream outputFile; AsnBuf outputBuf; size_t encodedLen; const size_t dataSize = 1024; char data[dataSize]; ChildInformation *ciPtr; PersonnelRecord pr; // build internal value of a PersonnelRecord pr.name = new Name; pr.name->givenName = "John"; // this calls pr.name->givenName.Set ("John"); pr.name->initial = "E"; pr.name->familyName = "Smith"; pr.title.Set ("The Big Cheese"); pr.employeeNumber = 99999; pr.dateOfHire.Set ("19820104"); pr.nameOfSpouse = new Name; pr.nameOfSpouse->givenName.Set ("Mary"); pr.nameOfSpouse->initial.Set ("L"); pr.nameOfSpouse->familyName.Set ("Smith"); pr.children = new PersonnelRecordSeqOf; ciPtr = pr.children->Append(); ciPtr->name = new Name; ciPtr->name->givenName.Set ("James"); ciPtr->name->initial.Set ("R"); ciPtr->name->familyName.Set ("Smith"); ciPtr->dateOfBirth.Set ("19570310"); ciPtr = pr.children->Append(); ciPtr->name = new Name; ciPtr->name->givenName.Set ("Lisa"); ciPtr->name->initial.Set ("M"); ciPtr->name->familyName.Set ("Smith"); ciPtr->dateOfBirth.Set ("19610621"); // set up buffer for writing to outputBuf.Init (data, dataSize); outputBuf.ResetInWriteRvsMode(); // encode the internal value we just build into the buffer if (!pr.BEncPdu (outputBuf, encodedLen)) cout << "failed encoding AnyTestType value" << endl; // open file to hold the BER value outputFile.open ("pr.ber"); if (!outputFile) { perror ("ofstream::open"); exit (1); } // copy the BER value from the buffer to the file outputBuf.ResetInReadMode(); for (; encodedLen > 0; encodedLen--) outputFile.put (outputBuf.GetByte()); cout << "Wrote the following BER PersonnelRecord value to pr.ber." << endl; cout << "Test it with \"def\" and \"indef\"." << endl; cout << pr << endl; return 0; }
main (int argc, char *argv[]) { ofstream outputFile; AsnBuf outputBuf; size_t encodedLen; size_t dataSize = 1024; #if HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS char data[dataSize]; #else char *data = new char[dataSize]; if (!data) return 1; #endif /* HAVE_VARIABLE_SIZED_AUTOMATIC_ARRAYS */ AnyTestType att; TSeq1 ts1; TSeq2 ts2; AttrValue1 *atv1ptr; AttrValue2 *atv2ptr; AsnInt intVal; AsnBool boolVal; AsnOcts octsVal ("Hi Mom"); OctsId octsIdVal = octsVal; AsnBits bitsVal; BitsId bitsIdVal (9); AsnReal realVal; // READ THIS!!! // you must be really careful when setting the // "value" field and "id" fields in an // ANY/ANY DEFINED BY type because "value" is a // "AsnType*" and will accept any // pointer value. It will even encode // the wrong value without complaining if you // set "value" to the wrong object. atv1ptr = att.intMap.Append(); atv1ptr->id = intId; intVal = -99; atv1ptr->anyDefBy.value = &intVal; atv1ptr = att.intMap.Append(); atv1ptr->id = boolId; boolVal = true; atv1ptr->anyDefBy.value = &boolVal; atv1ptr = att.intMap.Append(); atv1ptr->id = octsId; atv1ptr->anyDefBy.value = &octsIdVal; atv1ptr = att.intMap.Append(); atv1ptr->id = bitsId; bitsIdVal.SetBit (0); bitsIdVal.ClrBit (1); bitsIdVal.SetBit (2); bitsIdVal.ClrBit (3); bitsIdVal.SetBit (4); bitsIdVal.ClrBit (5); bitsIdVal.SetBit (6); bitsIdVal.ClrBit (7); bitsIdVal.SetBit (8); bitsIdVal.ClrBit (9); atv1ptr->anyDefBy.value = &bitsIdVal; atv1ptr = att.intMap.Append(); atv1ptr->id = realId; realVal = 108.3838; atv1ptr->anyDefBy.value = &realVal; // now do TSeq2 with same vals but use OID as identifier atv2ptr = att.oidMap.Append(); atv2ptr->id = intOid; atv2ptr->anyDefBy.value = &intVal; atv2ptr = att.oidMap.Append(); atv2ptr->id = boolOid; atv2ptr->anyDefBy.value = &boolVal; atv2ptr = att.oidMap.Append(); atv2ptr->id = octsOid; atv2ptr->anyDefBy.value = &octsVal; atv2ptr = att.oidMap.Append(); atv2ptr->id = bitsOid; bitsVal = bitsIdVal; // copy bits atv2ptr->anyDefBy.value = &bitsVal; atv2ptr = att.oidMap.Append(); atv2ptr->id = realOid; atv2ptr->anyDefBy.value = &realVal; outputBuf.Init (data, dataSize); outputBuf.ResetInWriteRvsMode(); if (!att.BEncPdu (outputBuf, encodedLen)) cout << "failed encoding AnyTestType value" << endl; outputFile.open ("att.ber"); if (!outputFile) { perror ("ofstream::open"); exit (1); } outputBuf.ResetInReadMode(); for ( ; encodedLen > 0; encodedLen--) outputFile.put (outputBuf.GetByte()); cout << "Wrote the following BER AnyTestType value to att.ber." << endl; cout << "Test it with \"def\" and \"indef\"" << endl; cout << att << endl; return 0; }