Handle ASN.1 specification of length in the indefinite form.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5048 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
oana 2012-05-08 08:42:59 +00:00
parent 8672ff9cbd
commit b2ff26d993
4 changed files with 105 additions and 14 deletions

View File

@ -43,8 +43,10 @@ int ASNLib::decodeLength(DataBlock& data) {
if (lengthByte & ASN_LONG_LENGTH) { // the length is represented on more than one byte
lengthByte &= ~ASN_LONG_LENGTH; /* turn MSB off */
if (lengthByte == 0)
return InvalidLengthOrTag;
if (lengthByte == 0) {
data.cut(-1);
return IndefiniteForm;
}
if (lengthByte > sizeof(int))
return InvalidLengthOrTag;
@ -88,6 +90,54 @@ DataBlock ASNLib::buildLength(DataBlock& data)
return lenDb;
}
int ASNLib::matchEOC(DataBlock& data)
{
/**
* EoC = 00 00
*/
XDebug(s_libName.c_str(),DebugAll,"::matchEOC() in data='%p'",&data);
if (data.length() < 2)
return InvalidLengthOrTag;
if (data[0] == 0 && data[1] == 0) {
data.cut(-2);
return 2;
}
return InvalidLengthOrTag;
}
int ASNLib::parseUntilEoC(DataBlock& data, int length)
{
if (length >= (int)data.length() || ASNLib::matchEOC(data) > 0)
return length;
while (data.length() && ASNLib::matchEOC(data) < 0) {
// compute tag portion length
AsnTag tag;
AsnTag::decode(tag,data);
length += tag.coding().length();
data.cut(-tag.coding().length());
// compute length portion length
int initLen = data.length();
int len = ASNLib::decodeLength(data);
length += initLen - data.length();
bool checkEoC = (len == ASNLib::IndefiniteForm);
if (!checkEoC && len < 0)
return length;
if (checkEoC) {
length = parseUntilEoC(data,length);
if (ASNLib::matchEOC(data) > 0)
length += 2;
}
else {
length += len;
data.cut(-len);
}
}
return length;
}
int ASNLib::decodeBoolean(DataBlock& data, bool* val, bool tagCheck)
{
/**

View File

@ -745,8 +745,9 @@ public:
enum Error {
InvalidLengthOrTag = -1,
ConstraintBreakError = -2,
ParseError,
InvalidContentsError
ParseError = -3,
InvalidContentsError = -4,
IndefiniteForm = -5,
};
/**
@ -1084,6 +1085,21 @@ public:
* @return The length of the data block length encoding
*/
static int encodeSet(DataBlock& data, bool tagCheck);
/**
* Verify the data for End Of Contents presence
* @param data Input block to verify
* @return Length of data consumed from the input data it the decoding was succesful, it should be 2 in case of success, -1 if the data doesn't match EoC
*/
static int matchEOC(DataBlock& data);
/**
* Extract length until a End Of Contents is found.
* @param data Input block for which to determine the length to End Of Contents
* @param length Length to which to add determined length
* @return Length until End Of Contents
*/
static int parseUntilEoC(DataBlock& data, int length = 0);
};
}

View File

@ -2529,13 +2529,16 @@ SS7TCAPError SS7TCAPTransactionANSI::decodeComponents(NamedList& params, DataBlo
// decode length of component portion
int len = ASNLib::decodeLength(data);
if (len < 0 || len != (int)data.length()) { // the length of the remaining data should be the same as the decoded length()
bool checkEoC = (len == ASNLib::IndefiniteForm);
if (!checkEoC && (len < 0 || len != (int)data.length())) { // the length of the remaining data should be the same as the decoded length()
error.setError(SS7TCAPError::General_BadlyStructuredCompPortion);
return error;
}
unsigned int compCount = 0;
while (data.length()) {
if (checkEoC && ASNLib::matchEOC(data) > 0)
break;
compCount++;
// decode component type
u_int8_t compType = data[0];
@ -4087,13 +4090,16 @@ SS7TCAPError SS7TCAPTransactionITU::decodeComponents(NamedList& params, DataBloc
// decode length of component portion
int len = ASNLib::decodeLength(data);
if (len < 0 || len != (int)data.length()) { // the length of the remaining data should be the same as the decoded length
bool checkEoC = (len == ASNLib::IndefiniteForm);
if (!checkEoC && (len < 0 || len != (int)data.length())) { // the length of the remaining data should be the same as the decoded length
error.setError(SS7TCAPError::General_BadlyStructuredCompPortion);
return error;
}
unsigned int compCount = 0;
while (data.length()) {
if (checkEoC && ASNLib::matchEOC(data) > 0)
break;
compCount++;
// decode component type
u_int8_t compType = data[0];

View File

@ -920,11 +920,21 @@ static bool decodeHex(const Parameter* param, MapCamelType* type, AsnTag& tag, D
child->setAttribute(s_encAttr,"hex");
int len = ASNLib::decodeLength(data);
if (len < 0)
bool checkEoC = (len == ASNLib::IndefiniteForm && tag.type() == AsnTag::Constructor);
if (!checkEoC && len < 0)
return false;
String octets;
octets.hexify(data.data(),(len > (int)data.length() ? data.length() : len),' ');
data.cut(-len);
if (checkEoC) {
DataBlock d(data.data(),data.length());
int l = ASNLib::parseUntilEoC(d);
octets.hexify(data.data(),l,' ');
data.cut(-l);
ASNLib::matchEOC(data);
}
else {
octets.hexify(data.data(),(len > (int)data.length() ? data.length() : len),' ');
data.cut(-len);
}
child->addText(octets);
return true;
}
@ -1051,7 +1061,9 @@ static bool decodeSeq(const Parameter* param, MapCamelType* type, AsnTag& tag, D
data.cut(-(int)tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
bool checkEoC = (len == ASNLib::IndefiniteForm);
len = (checkEoC ? data.length() : len);
if (!checkEoC && len < 0)
return false;
int initLen = data.length();
@ -1061,7 +1073,7 @@ static bool decodeSeq(const Parameter* param, MapCamelType* type, AsnTag& tag, D
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && params->name) {
if (initLen - (int)data.length() >= len)
if ((initLen - (int)data.length() >= len) || (checkEoC && ASNLib::matchEOC(data) > 0))
break;
AsnTag childTag;
AsnTag::decode(childTag,data);
@ -1133,16 +1145,19 @@ static bool decodeSeqOf(const Parameter* param, MapCamelType* type, AsnTag& tag,
data.cut(-(int)tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
bool checkEoC = (len == ASNLib::IndefiniteForm);
if (!checkEoC && len < 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int initLength = data.length();
int payloadLen = len;
int payloadLen = (checkEoC ? data.length() : len);
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && !TelEngine::null(params->name) && payloadLen) {
if (checkEoC && ASNLib::matchEOC(data) > 0)
break;
AsnTag childTag;
AsnTag::decode(childTag,data);
if (!decodeParam(params,childTag,data,child,addEnc,err)) {
@ -1214,12 +1229,14 @@ static bool decodeChoice(const Parameter* param, MapCamelType* type, AsnTag& tag
return false;
XDebug(&__plugin,DebugAll,"decodeChoice(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
bool checkEoC = false;
if (param->tag != s_noTag) {
if (param->tag != tag)
return false;
data.cut(-(int)tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
checkEoC = (len == ASNLib::IndefiniteForm);
if (!checkEoC && len < 0)
return false;
}
XmlElement* child = new XmlElement(param->name);
@ -1234,6 +1251,8 @@ static bool decodeChoice(const Parameter* param, MapCamelType* type, AsnTag& tag
params++;
continue;
}
if (checkEoC)
ASNLib::matchEOC(data);
return true;
}
if (err != TcapXApplication::DataMissing) {