aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/base/diameter_capx.erl
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2015-02-12 11:41:59 +0100
committerAnders Svensson <[email protected]>2015-03-24 10:57:02 +0100
commit1590920c910c030369fbf871b63f6836b988e90a (patch)
treebf2b2f8e353f2f0a8f80196b3f143890e45f3482 /lib/diameter/src/base/diameter_capx.erl
parent75ee72b4e1d288b1d96194d0e352eb0c73db4a6f (diff)
downloadotp-1590920c910c030369fbf871b63f6836b988e90a.tar.gz
otp-1590920c910c030369fbf871b63f6836b988e90a.tar.bz2
otp-1590920c910c030369fbf871b63f6836b988e90a.zip
Add service_opt() string_decode
To control whether stringish Diameter types are decoded to string or left as binary. The motivation is the same as in the parent commit: to avoid large strings being copied when incoming Diameter messages are passed between processes; or *if* in the case of messages destined for handle_request and handle_answer callbacks, since these are decoded in the dedicated processes that the callbacks take place in. It would be possible to do something about other messages without requiring an option, but disabling the decode is the most effective. The value is a boolean(), true being the default for backwards compatibility. Setting false causes both diameter_caps records and decoded messages to contain binary() in relevant places that previously had string(): diameter_app(3) callbacks need to be prepared for the change. The Diameter types affected are OctetString and the derived types that can contain arbitrarily large values: OctetString, UTF8String, DiameterIdentity, DiameterURI, IPFilterRule, and QoSFilterRule. Time and Address are unaffected. The DiameterURI decode has been redone using re(3), which both simplifies and does away with a vulnerability resulting from the conversion of arbitrary strings to atom. The solution continues the use and abuse of the process dictionary for encode/decode purposes, last seen in commit 0f9cdba.
Diffstat (limited to 'lib/diameter/src/base/diameter_capx.erl')
-rw-r--r--lib/diameter/src/base/diameter_capx.erl40
1 files changed, 34 insertions, 6 deletions
diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
index 93548ecafd..7dc61f229f 100644
--- a/lib/diameter/src/base/diameter_capx.erl
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -50,7 +50,8 @@
-export([build_CER/2,
recv_CER/3,
recv_CEA/3,
- make_caps/2]).
+ make_caps/2,
+ binary_caps/1]).
-include_lib("diameter/include/diameter.hrl").
-include("diameter_internal.hrl").
@@ -115,7 +116,8 @@ mk_caps(Caps0, Opts) ->
-define(SC(K,F),
set_cap({K, Val}, {Caps, #diameter_caps{F = false} = C}) ->
- {Caps#diameter_caps{F = cap(K, Val)}, C#diameter_caps{F = true}}).
+ {Caps#diameter_caps{F = cap(K, copy(Val))},
+ C#diameter_caps{F = true}}).
?SC('Origin-Host', origin_host);
?SC('Origin-Realm', origin_realm);
@@ -375,10 +377,10 @@ capx_to_caps(CEX, Dict) ->
'Firmware-Revision',
'AVP'],
CEX),
- #diameter_caps{origin_host = OH,
- origin_realm = OR,
+ #diameter_caps{origin_host = copy(OH),
+ origin_realm = copy(OR),
vendor_id = VId,
- product_name = PN,
+ product_name = copy(PN),
origin_state_id = OSI,
host_ip_address = IP,
supported_vendor_id = SV,
@@ -389,6 +391,32 @@ capx_to_caps(CEX, Dict) ->
firmware_revision = FR,
avp = X}.
+%% Copy binaries to avoid retaining a reference to a large binary
+%% containing AVPs we aren't interested in.
+copy(B)
+ when is_binary(B) ->
+ binary:copy(B);
+
+copy(T) ->
+ T.
+
+%% binary_caps/1
+%%
+%% Encode stringish capabilities with {string_decode, false}.
+
+binary_caps(Caps) ->
+ lists:foldl(fun bcaps/2, Caps, [#diameter_caps.origin_host,
+ #diameter_caps.origin_realm,
+ #diameter_caps.product_name]).
+
+bcaps(N, Caps) ->
+ case element(N, Caps) of
+ undefined ->
+ Caps;
+ V ->
+ setelement(N, Caps, iolist_to_binary(V))
+ end.
+
%% ---------------------------------------------------------------------------
%% ---------------------------------------------------------------------------