aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2013-05-29 18:40:19 +0200
committerAnders Svensson <[email protected]>2013-05-29 18:40:19 +0200
commitaecb2d0c041d43659f57235fe6b14478663e6444 (patch)
tree3981d03c97d8a408d9c146c263c8c732efbae594
parent048a67e6f34df0180bc8d2d0aba7f3b36d234a21 (diff)
parenta732bb3496cf24e62b607293de7c5ae49b3891ce (diff)
downloadotp-aecb2d0c041d43659f57235fe6b14478663e6444.tar.gz
otp-aecb2d0c041d43659f57235fe6b14478663e6444.tar.bz2
otp-aecb2d0c041d43659f57235fe6b14478663e6444.zip
Merge branch 'anders/diameter/avp_length_failure/OTP-11026' into maint
* anders/diameter/avp_length_failure/OTP-11026: Fix decode failure when AVP Length < 8
-rw-r--r--lib/diameter/src/base/diameter_codec.erl2
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl53
2 files changed, 42 insertions, 13 deletions
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index e446a0209c..09b99b2cae 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -427,6 +427,8 @@ split_avp(Bin) ->
<<Code:32, Flags:1/binary, Length:24, Rest/bitstring>>
= Bin,
+ 8 =< Length orelse ?THROW(invalid_avp_length),
+
DataSize = Length - 8, % size(Code+Flags+Length) = 8 octets
PadSize = (4 - (DataSize rem 4)) rem 4,
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 2684ab8fe4..3878d6717a 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -49,7 +49,9 @@
send_unsupported_app/1,
send_error_bit/1,
send_unsupported_version/1,
- send_invalid_avp_bits/1,
+ send_long_avp_length/1,
+ send_short_avp_length/1,
+ send_zero_avp_length/1,
send_invalid_avp_length/1,
send_invalid_reject/1,
send_long/1,
@@ -268,7 +270,9 @@ tc() ->
send_unsupported_app,
send_error_bit,
send_unsupported_version,
- send_invalid_avp_bits,
+ send_long_avp_length,
+ send_short_avp_length,
+ send_zero_avp_length,
send_invalid_avp_length,
send_invalid_reject,
send_long,
@@ -481,13 +485,20 @@ send_unsupported_version(Config) ->
['STA', _SessionId, {'Result-Code', ?UNSUPPORTED_VERSION} | _]
= call(Config, Req).
-%% Send a request containing an incorrect AVP length.
-send_invalid_avp_bits(Config) ->
+%% Send a request containing an AVP length > data size.
+send_long_avp_length(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
?answer_message(?INVALID_AVP_BITS)
= call(Config, Req).
+%% Send a request containing an AVP length < data size.
+send_short_avp_length(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+
+ ['STA', _SessionId, {'Result-Code', ?INVALID_AVP_LENGTH} | _]
+ = call(Config, Req).
+
%% Send a request containing an AVP length that doesn't match the
%% AVP's type.
send_invalid_avp_length(Config) ->
@@ -496,6 +507,13 @@ send_invalid_avp_length(Config) ->
['STA', _SessionId, {'Result-Code', ?INVALID_AVP_LENGTH} | _]
= call(Config, Req).
+%% Send a request containing an AVP whose advertised length is < 8.
+send_zero_avp_length(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+
+ ?answer_message(?INVALID_AVP_BITS)
+ = call(Config, Req).
+
%% Send a request containing 5xxx errors that the server rejects with
%% 3xxx.
send_invalid_reject(Config) ->
@@ -804,25 +822,32 @@ log(#diameter_packet{bin = Bin} = P, T)
%% prepare/4
-prepare(Pkt, Caps, send_invalid_avp_bits, #group{client_dict0 = Dict0}
- = Group) ->
+prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+ when N == send_long_avp_length;
+ N == send_short_avp_length;
+ N == send_zero_avp_length ->
Req = prepare(Pkt, Caps, Group),
- %% Last AVP in our STR is Termination-Cause of type Unsigned32:
- %% set its length improperly.
+ %% Second last AVP in our STR is Auth-Application-Id of type
+ %% Unsigned32: set AVP Length to a value other than 12.
#diameter_packet{header = #diameter_header{length = L},
bin = B}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
- Offset = L - 7, %% to AVP Length
- <<H:Offset/binary, 12:24/integer, T:4/binary>> = B,
- E#diameter_packet{bin = <<H/binary, 13:24/integer, T/binary>>};
+ Offset = L - 7 - 12, %% to AVP Length
+ <<H:Offset/binary, 12:24/integer, T:16/binary>> = B, %% assert
+ AL = case N of
+ send_long_avp_length -> 13;
+ send_short_avp_length -> 11;
+ send_zero_avp_length -> 0
+ end,
+ E#diameter_packet{bin = <<H/binary, AL:24/integer, T/binary>>};
prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
when N == send_invalid_avp_length;
N == send_invalid_reject ->
Req = prepare(Pkt, Caps, Group),
%% Second last AVP in our STR is Auth-Application-Id of type
- %% Unsigned32: Send a value of length 8.
+ %% Unsigned32: send data of length 8.
#diameter_packet{header = #diameter_header{length = L},
bin = B0}
= E
@@ -944,7 +969,9 @@ answer(Pkt, Req, _Peer, Name, #group{client_dict0 = Dict0}) ->
[Dict:rec2msg(R) | Vs].
answer(Rec, [_|_], N)
- when N == send_invalid_avp_bits;
+ when N == send_long_avp_length;
+ N == send_short_avp_length;
+ N == send_zero_avp_length;
N == send_invalid_avp_length;
N == send_invalid_reject ->
Rec;