aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2013-01-11 11:02:40 +0100
committerBjörn Gustavsson <[email protected]>2013-01-22 19:20:14 +0100
commit986e51aa44e78c6fcc566cc8a08827b46325739f (patch)
treed1def7667010a1043e2e3aa35c3291bb214d7064
parent2e57d4603575f492f54409e8235806ee6702944c (diff)
downloadotp-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.erl5
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl52
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.