diff options
author | Björn Gustavsson <[email protected]> | 2013-01-11 11:02:40 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2013-01-22 19:20:14 +0100 |
commit | 986e51aa44e78c6fcc566cc8a08827b46325739f (patch) | |
tree | d1def7667010a1043e2e3aa35c3291bb214d7064 | |
parent | 2e57d4603575f492f54409e8235806ee6702944c (diff) | |
download | otp-986e51aa44e78c6fcc566cc8a08827b46325739f.tar.gz otp-986e51aa44e78c6fcc566cc8a08827b46325739f.tar.bz2 otp-986e51aa44e78c6fcc566cc8a08827b46325739f.zip |
Fix EXTERNAL 1990/1994 conversion information loss
There are two different definitions of the EXTERNAL data type in ASN.1:
the original from 1990 and an updated from 1994. Both defintions
are encoded in the same way (in BER). There are still
systems in use that use the old definition of EXTERNAL, so the
asn1 application must still support both.
It has been decided that the asn1 application should handle both
the forms without any compiler options. Internally the asn1 application
uses the 1990 definition. The encode functions will accept both
definitions, but translate the 1994 format to the 1990 format
if needed. When decoding, it will decode to the 1990 definition format
first and then translate to the 1994 defintion format.
One problem with this approach is that the conversion to the 1994
format may not be loss-less (where the 1990 defintion had a CHOICE
between an OPEN TYPE, OCTET STRING, or BIT STRING, the 1994 definition
only supports an OCTET STRING), and therefore it might not be possible
to correctly re-encode the data in the 1990 format.
It seems that the only reliable way to handle that problem is to not
do the conversion to the 1994 format if the conversion is not
loss-less. (There is an attempt when translating to the 1990 format
to recover the CHOICE alternative based on the Erlang type of
the data value, but that is neither reliable nor future-proof.)
That is, when decoding an EXTERNAL value, the resulting
tuple could either conform to the 1990 or 1994 definition, and
applications must be prepared to handle that.
The mail conversation where this issue was first reported can be
found here:
http://erlang.org/pipermail/erlang-questions/2011-April/057697.html
Reported-by: Harald Welte <[email protected]>
-rw-r--r-- | lib/asn1/src/asn1rtt_ext.erl | 5 | ||||
-rw-r--r-- | lib/asn1/test/testContextSwitchingTypes.erl | 52 |
2 files changed, 37 insertions, 20 deletions
diff --git a/lib/asn1/src/asn1rtt_ext.erl b/lib/asn1/src/asn1rtt_ext.erl index 59dbcc16bd..7510b01f17 100644 --- a/lib/asn1/src/asn1rtt_ext.erl +++ b/lib/asn1/src/asn1rtt_ext.erl @@ -62,8 +62,11 @@ transform_to_EXTERNAL1994({'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}=V) -> {'EXTERNAL_identification_context-negotiation',IndRef,DRef}} end, case Encoding of - {_,Val} when is_list(Val); is_binary(Val) -> + {'octet-aligned',Val} when is_list(Val); is_binary(Val) -> + %% Transform to the EXTERNAL 1994 definition. {'EXTERNAL',Identification,Data_v_desc,Val}; _ -> + %% Keep the EXTERNAL 1990 definition to avoid losing + %% information. V end. diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl index 4f67942922..f06cc7c117 100644 --- a/lib/asn1/test/testContextSwitchingTypes.erl +++ b/lib/asn1/test/testContextSwitchingTypes.erl @@ -52,22 +52,36 @@ test(Config) -> check_EXTERNAL({'EXTERNAL',Identif,DVD,DV})-> - ?line ok=check_EXTERNAL_Idef(Identif), - ?line ok = check_EXTERNAL_DVD(DVD), - ?line ok = check_EXTERNAL_DV(DV). -check_EXTERNAL_Idef({Alt,_}) when Alt=='context-negotiation'; - Alt=='presentation-context-id'; - Alt==syntax -> - ok; -check_EXTERNAL_Idef(I) -> - {error,"failed on identification alternative",I}. -check_EXTERNAL_DVD(DVD) when is_list(DVD) -> - ok; -check_EXTERNAL_DVD(asn1_NOVALUE) -> - ok; -check_EXTERNAL_DVD(DVD) -> - {error,"failed on data-value-descriptor alternative",DVD}. -check_EXTERNAL_DV(DV) when is_list(DV);is_binary(DV) -> - ok; -check_EXTERNAL_DV(DV) -> - {error,"failed on data-value alternative",DV}. + %% EXTERNAL in the 1994 format. + case Identif of + {'context-negotiation',_} -> + ok; + {'presentation-context-id',Id} -> + true = is_integer(Id); + {syntax,ObjId} -> + check_object_identifier(ObjId) + end, + check_EXTERNAL_DVD(DVD), + check_EXTERNAL_DV(DV); +check_EXTERNAL({'EXTERNAL',ObjId,IndirectRef,Descriptor,Enc})-> + %% EXTERNAL in the 1990 format. + check_object_identifier(ObjId), + true = is_integer(IndirectRef), + true = is_binary(Descriptor) orelse is_list(Descriptor), + case Enc of + {arbitrary,_} -> ok; + {'single-ASN1-type',_} -> ok; + {'octet-aligned',_} -> ok + end. + +check_EXTERNAL_DVD(DVD) when is_list(DVD) -> ok; +check_EXTERNAL_DVD(asn1_NOVALUE) -> ok. + +check_EXTERNAL_DV(DV) when is_list(DV); is_binary(DV) -> ok. + +check_object_identifier(Tuple) when is_tuple(Tuple) -> + %% An OBJECT IDENTIFIER is a tuple with integer elements. + case [E || E <- tuple_to_list(Tuple), + not is_integer(E)] of + [] -> ok + end. |