This document explains how to configure Asn1Browser.
Asn1Browser analyzes and displays ASN.1 coded messages. It needs at least the decoding classes associated to an ASN.1 syntax. It also needs information to extract ASN.1 data from a data flow (over TCP/IP or read in a log file).
All these information are written in profile files.
Asn1Browser is configured through text files named "profiles*.cfg" (where "*" matches any string). These files must be stored in "<installation directory>/asn1Browser" directory. You have to edit a profile file to create or modify a profile definition.
A profile file may contain one or more profile definitions.
Each specific execution context of Asn1Browser is defined in a profile. The browser is divided in several layers: network layer, file layer, protocol layer and finally ASN.1 layer. To each layer corresponds a specific treatment that can be refined within the profile definition.
The profile contains information for each layer and allows the user to refine behavior at each step of the analysis.
A profile definition contains :
The default profile file defines a profile called "Asn1Sample" :
; Profile definition
profile
{
id = "Asn1Sample"
protocol = "Asn1Sample-protocol"
asn1API = "asn1API/Asn1Sample/lib/Asn1Sample.jar"
messageFilter = "mf_Null"
fileFilter = "ff_asb_record/mf_Null"
fileFilter = "ff_asb_ip_log/mf_Ber"
display = "Asn1Sample-display"
}
|
The references ("uniGone-protocol", "ff_asb_record"...) are the identifiers of the corresponding definitions in the file.
A protocol identifies the abstract syntax PDU and the encoding rules needed to decode ASN.1 data. A protocol definition contains :
The default profile file defines the protocol associated to the "Asn1Sample" profile:
protocol
{
id = "Asn1Sample-protocol"
abstractSyntaxPDUClass = "Asn1Sample.asn1Sample.Basic_types"
; filterClass =
; filterClassLocation =
|
A filter is used to check that data fit the protocol. If no filter is defined then data are supposed to fit the protocol and will thus be analyzed. Normally, when many protocols are defined in the profile, each require (possibly except the last) a specific filter.
Asn1Browser provides the following filters :
If ever 2 protocols have got the same filter class applied (the comparison is made on the full name of the class and parameters), then the decoder will try all protocols with the same filter (since it cannot decide which one must be used) and then may give several results (see Protocols decodings).
Note: don't forget to wrap your filter class names and parameters with "".
Here is an example of a protocol that defines a filter consisting in checking the first byte of the PDU is 0xA1, 0xA2, 0xA3 or 0xA4. This is treated as a discriminator that is not removed and thus part of the PDU.
protocol
{
id = "HI2-IRIContent"
abstractSyntaxPDUClass = "ETSI_LI.hi2operations.IRIContent"
filterClass = "com.unigone.asn1Browser.asn1.protocol.OneByteDiscriminatorFilter"
filterClassParameters = "0xA1|0xA2|0xA3|0xA4, false"
encodingRules = "BER"
}
|
The user can write its own filters. A filter is a Java class that implements the following methods :
Specific parameters can be passed to this class using filterClassParameters pattern (e.g. filterClassParameters = "0xC5" ). If many parameters are to be passed they must be "," separated. If ever parameters are passed then the protocol class implementor must write the "setParameters(String[])" method. The parameters are passed as a String array and parameters are thus String that must be converted in this method by the implementor.
An example of such a method is for the OneByteDiscriminatorFilter filter assuming one mandatory parameter is given and one optional :
public static void setParameters(String[] parameters)
{
StringTokenizer discrs = new StringTokenizer(parameters[0],"|");
discriminators = new byte[discrs.countTokens()];
int i = 0;
while(discrs.hasMoreTokens())
{
try
{
String t = discrs.nextToken().trim();
Integer pi = Integer.decode(t);
int b = (int)pi.intValue();
if (0 <= b && b <= 255)
discriminators[i] = (byte)b;
}
catch (NumberFormatException ex){}
i++;
}
if (parameters.length == 2)
{
Boolean b = Boolean.valueOf(parameters[1].trim());
removeDiscriminator = b.booleanValue();
}
}
The encoding rules are represented by a string. The following strings are supported :
By default, the decoder that is defined by the encoding rules is a validating decoder, which means that the constraints specified in the ASN.1 syntax will be checked after the PDU has been decoded. One can however refine this behavior using specific properties. The validating property is to be defined this way:
protocol
{
id = "HI2-IRIContent"
abstractSyntaxPDUClass = "ETSI_LI.hi2operations.IRIContent"
filterClass = "com.unigone.asn1Browser.asn1.protocol.OneByteDiscriminatorFilter"
filterClassParameters = "0xA1|0xA2|0xA3|0xA4, false"
encodingRules = "BER
decoderProperties
{
validating="false"
}
}
|
On a TCP-IP link, there is a need to control the length of a message because sent messages can be received in separate TCP-IP packets (depending of the data charge on the link). Therefore, the applications must know when a message is complete and a simple way to achieve that is to give the length of a message in a specialized header. The message filter technic allows the choice of the specialized header. During establishment pahse, some bytes may be sent to synchronize applications, those bytes must be ignored in order not to break the length filtering.
A message filter definition contains:
Messages to be ignored are identified giving a list (comma separated) of bytes arrays like this: "0x42, 0x25 0x43 0x56" where a byte array content is space separated. This specifies that any messages that equal exactly either 0x42 either 0x25 0x43 0x56 will be ignored by the message filter which will thus not consider those bytes as headers giving potentially a length. The wildcard "*" may be used to specify only the start of a message. For example, "0x42, 0x25 *" specify that all messages starting with 0x42, 0x25 shall be ignored by the message filter. Note that the wildcard is only accepted in last position, otherwise it will be rejected.
If an ignored message is encountered, the filter will :
Many message filter definitions are available in the default profile file. They may be reused in other profile definitions.
The LengthHeaderFilter is a configurable filter that assumes the length of the PDU is given in a specific header. This filter considers the header is organized this way:
-------------------------------------------------------------------------------------
| bytes before length | length | first bytes of PDU to ignore | rest of PDU ... |
-------------------------------------------------------------------------------------
\_____________________________/\_____________________________________________...______/
V V
header PDU
In the above schema, we can see the header is defined with:
The following filter defines a filter for a header that ignores all messages
starting with 20,00 or 20,01 or 20,02 and accepts all other messages assuming
the header has 2 bytes to ignore, a length defined on one byte and no bytes
to ignore in PDU. The length is assumed to count only the size of the PDU excluding
the header.
messageFilter
{
id = "mf_LengthHeader"
class = "com.unigone.asn1Browser.net.messageFilter.LengthHeaderFilter"
; Parameters for this filter are to be defined as follows (in this strict order) :
; param 1 : number of bytes before length to ignore
; param 2 : number of bytes for length (assuming most significant byte first)
; param 3 : number of first bytes in PDU to ignore
; param 4 : include header bytes in length (true or false)
; param 5 : ignore Most Significant Bit in length (true or false)
classParameters="2,1,0,false,false"
ignoredMessages = "0x20 0x00 *,0x20 0x01 *,0x20 0x02 *"
}
|
Actually, many other pre-defined filters exposed after could be defined using the LengthHeaderFilter.
The TpktFilter is based on the RFC 1006. A TPKT packet is made with 2 parts. The first one is a header and the second one is the PDU. The header is composed of the "vrsn" byte (value is 3 for RFC 1006), a reserved byte (value is 0) and the packet length in bytes (including the header).
messageFilter
{
id = "mf_Tpkt"
class = "com.unigone.asn1Browser.net.messageFilter.tpktFilter.TpktFilter"
}
|
The TpktExtra1Filter, based on the TpktFilter, has been specially described for considering that the first byte of the PDU is to be ignored by the browser (case of a protocol discriminant for example).
messageFilter
{
id = "mf_TpktExtra1"
class = "com.unigone.asn1Browser.net.messageFilter.tpktFilter.TpktFilterExtra1"
}
|
The TpktExtra2Filter, based on the TpktFilter, has been specially described for considering that the first two bytes of the PDU are to be ignored by the browser.
messageFilter
{
id = "mf_TpktExtra2"
class = "com.unigone.asn1Browser.net.messageFilter.tpktFilter.TpktFilterExtra2"
}
|
The PduLengthFilter extracts the ASN.1 PDU considering the PDU is preceeded by two bytes giving the length in bytes of it. The ignored messages line has been commented: it may be used to make the message filter ignore 0x42, 0x50, 0x45 0x58 0x49 0x54 messages.
messageFilter
{
id = "mf_PduLength"
class = "com.unigone.asn1Browser.net.messageFilter.pduLengthFilter.PduLengthFilter"
; ignoredMessages = "0x42,0x50,0x45 0x58 0x49 0x54"
}
|
The NullFilter considers that the complete message represents the ASN.1 data with no limit. It is generally used by the browser to analyze data in text files.
messageFilter
{
id = "mf_Null"
class = "com.unigone.asn1Browser.net.messageFilter.nullFilter.NullFilter"
}
|
The SinglePduFilter is used to read files that contain one, and only one, ASN.1 PDU. When the end of the file is reached then the filter considers that the received data are ASN.1 data and represent one PDU. It is generally used by the browser to analyze data in binary files.
messageFilter
{
id = "mf_SinglePdu"
class = "com.unigone.asn1Browser.net.messageFilter.nullFilter.SinglePduFilter"
}
|
The BerFilter considers that there is no added length information other than the inner BER (Basic Encoding Rules) length.
messageFilter
{
id = "mf_Ber"
class = "com.unigone.asn1Browser.net.messageFilter.asn1Filter.BerFilter"
}
|
A message filter is a class extending the com.unigone.asn1Browser.net.messageFilter.MessageFilter class. It must implement the protected abstract method handleNewData(RawData session, Position position). This method is invoked each time a MessageFilter receives an event containing data from the lower level (network, TCP/IP sockets or file reader level). The Message Filter instance is in a while (handleNewData(session, position)) loop. Before sending an event containing a complete data unit to the lower level (ASN.1 analyzer level), the MessageFilter instance handles a "session" that serves to memorize incoming data.
The "session" parameter is the object containing the data, "position" is an object that is used to select where and how to select a data unit in the session.
The com.unigone.asn1Browser.net.messageFilter.RawData methods used by message
filter "handleNewData" method are :
- gotoMark() : when there is not enough data according to the filter definition
- available() : gives the number of bytes that are available in the session
- getByte() : returns the next byte in the session and reads it (meaning this
byte will be removed when the data unit will be built from the session - it
will then not be given to the upper level)
- getOffset() : gives the relative offset of the internal buffer, it must be
invoked when an error has occurred in the current buffer, in conjonction with
Position.valid = false.
The com.unigone.asn1Browser.net.messageFilter.Position fields used by message
filter "handleNewData" method are :
- start : sets the start of the data unit in the session
- length : set the data unit lenght in the session
- valid : says if the position can be considered valid or not (always true unless
a strong error has occurred when reading the current buffer). By default valid
is true.
The "handleNewData" method will return true if the data unit is complete or if the reading must be stopped for any reason and false otherwise.
A simple example is given for the Null filter :
package com.unigone.asn1Browser.net.messageFilter.nullFilter;
import com.unigone.asn1Browser.net.messageFilter.*;
public class NullFilter extends MessageFilter
{
protected boolean handleNewData(RawData session, MessagePosition position)
{
if (session.available() == 0)
return false;
position.start = 0;
position.length = session.available();
return(true);
}
}
Another example is the PduLengthFilter :
package com.unigone.asn1Browser.net.messageFilter.nullFilter;
import com.unigone.asn1Browser.net.messageFilter.*;
public class NullFilter extends MessageFilter
{
protected boolean handleNewData(RawData session, MessagePosition position)
{
int length;
length = getPduLength(session);
if (length == 0)
{
session.gotoMark();
return false;
}
if (session.available() < length)
{
session.gotoMark();
return false;
}
position.start = 2;
position.length = length;
return true;
}
int getPduLength(RawData session)
{
int length = 0;
/*
** get number of available bytes
*/
if (session.available() < 2)
{
return 0;
}
length = session.getByte();
length <<= 8;
length |= (0x00FF & session.getByte());
return length;
}
}
Note : if the available message filters don't fit your needs, a specific one may be written by our support team. Email your specific request to uniGone.
Generally applications exchanging messages generate log files giving the data they receive and the data they send over the link used to communicate. Those files (if the data are ASN.1 data) can be analyzed by Asn1Browser.
The file filters are powerfull means to extract data from a text (ASCII) file or a binary file.
Data recorded in a log file are not necessarily "pure" ASN.1 data. ASN.1 data may be wrapped by others bytes. A message filter is needed to extract the ASN.1 data. That is why in a profile definition, a file filter reference comes always with a message filter reference.
Many file filter definitions are available in the default profile file. They may be reused in other profile definitions.
Note : if the available file filters don't fit your needs, a specific one may be written for you. Email your request to uniGone.
The extraction of the ASN.1 data is achieved through the description of patterns that will help to distinguish the ASCII strings containing the ASN.1 data. This description is made using regular expressions.
A text file filter definition contains :
The ASN.1 data are considered as being an hexadecimal dump of the true data (the separators are "empty seprator", blanks or tabs). Once a line matching idEndDataPattern has been analyzed (or at the end of the file), the message is considered complete.
Note : "a bcde" is interpreted as "ab cd 0e".
The file filter allowing the reading of record generated by Asn1Browser is :
fileFilter
{
id = "ff_asb_record"
class = "com.unigone.asn1Browser.file.dataFileReader.pattern.Pattern"
_checkNbline = 10
_description = "Asn1Browser record files"
checkPattern = "Asn1Browser.*asb_record"
filterIfTruePattern = "^;"
toServerPattern = "^>"
toClientPattern = "^<"
idHoroPattern = "^[<>]"
getHoroPattern = "[0-9]+:[0-9]+:[0-9]+.[0-9]+"
idStartDataPattern = "^[^<>].....:"
idDataPattern = "^......:"
idSkipBolDataPattern = "^......:"
idSkipEolDataPattern = "\|.*$"
idEndDataPattern = "^$"
}
|
A binary file filter definition contains :
The binary file filter definition available in the default profile file is :
fileFilter
{
id = "ff_binary"
class = "com.unigone.asn1Browser.file.dataFileReader.binary.Binary"
_description = "Binary file"
}
|
Note : unlike the text file filter, the binary file filter has no mean to check that it is the right filter. When it is used it always works ! So it is recommended to use the binary file filter at the last position in the profile definition.
By default, Asn1Browser uses the root node characteristics of a decoded PDU when a short label is needed to display the PDU. To display another node, you must specifies its path. A path is a string composed of identifiers separated by a dot. The first identifier is the type name of the PDU and the following identifiers are the names of the embedded components. You also use its type name to refer to a specific enclosed component of an OPEN type. A wildcard "*" represents the unknown enclosed component of the CHOICE and OPEN type.
A display definition contains :
The default profile file defines the display associated to the "Asn1Sample" profile :
display
{
id = "Asn1Sample-display"
shortLabel = "Basic_types.*"
}
|
With the ROSE and CSTA (phase 2) protocols a display definition may be :
display
{
id = "ROSE-CSTAp2"
shortLabel="ROS.invoke.argument.CSTAEventReportArgument.eventSpecificInfo.callEvent.*"
shortLabel="ROS.invoke.argument.CSTAEventReportArgument.eventSpecificInfo.agentStateEvent.*"
shortLabel="ROS.invoke.argument.*"
shortLabel="ROS.returnResult.result.result.*"
shortLabel="ROS.*"
}
|