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:
parent
8672ff9cbd
commit
b2ff26d993
|
@ -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)
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue