aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2015-03-24 13:20:36 +0100
committerAnders Svensson <[email protected]>2015-03-27 07:21:27 +0100
commitf3e95a4d4278fda5a0648943020bdf0026219f7c (patch)
tree356dd6f2f5373c4f9417bec0d4ff9b598169af9b
parent545ff7783cebddc2ca5b2af67a6f13b1a01a4d03 (diff)
downloadotp-f3e95a4d4278fda5a0648943020bdf0026219f7c.tar.gz
otp-f3e95a4d4278fda5a0648943020bdf0026219f7c.tar.bz2
otp-f3e95a4d4278fda5a0648943020bdf0026219f7c.zip
Limit DiameterURI ports to 0-65535 digits on decode
A port number is a 16-bit integer, but the regexp used to parse it in commit 1590920 slavishly followed the RFC 6733 grammar in matching an arbitrary number of digits. Make decode fail if it's anything more than 5, to avoid doing erlang:list_to_integer/1 on arbitrarily large lists. Also make it fail if the resulting integer is outside of the expected range.
-rw-r--r--lib/diameter/src/base/diameter_types.erl12
-rw-r--r--lib/diameter/test/diameter_codec_test.erl6
2 files changed, 14 insertions, 4 deletions
diff --git a/lib/diameter/src/base/diameter_types.erl b/lib/diameter/src/base/diameter_types.erl
index fe7613541c..96407efc09 100644
--- a/lib/diameter/src/base/diameter_types.erl
+++ b/lib/diameter/src/base/diameter_types.erl
@@ -566,17 +566,25 @@ msb(false) -> ?TIME_2036.
scan_uri(Bin) ->
RE = "^(aaas?)://"
"([-a-zA-Z0-9.]+)"
- "(:([0-9]+))?"
+ "(:0{0,5}([0-9]{1,5}))?"
"(;transport=(tcp|sctp|udp))?"
"(;protocol=(diameter|radius|tacacs\\+))?$",
+ %% A port number is 16-bit, so an arbitrary number of digits is
+ %% just a vulnerability, but provide a little slack with leading
+ %% zeros in a port number just because the regexp was previously
+ %% [0-9]+ and it's not inconceivable that a value might be padded.
+ %% Don't fantasize about this padding being more than the number
+ %% of digits in the port number proper.
{match, [A, DN, PN, T, P]} = re:run(Bin,
RE,
[{capture, [1,2,4,6,8], binary}]),
Type = to_atom(A),
{PN0, T0} = defaults(diameter_codec:getopt(rfc), Type),
+ PortNr = to_int(PN, PN0),
+ 0 = PortNr bsr 16, %% assert
#diameter_uri{type = Type,
fqdn = from_bin(DN),
- port = to_int(PN, PN0),
+ port = PortNr,
transport = to_atom(T, T0),
protocol = to_atom(P, diameter)}.
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index 854b71ba93..11fa82cfa1 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -352,14 +352,16 @@ values('DiameterURI') ->
{[],
["aaa" ++ S ++ "://diameter.se" ++ P ++ Tr ++ Pr
|| S <- ["", "s"],
- P <- ["", ":1234"],
+ P <- ["", ":1234", ":0", ":65535"],
Tr <- ["" | [";transport=" ++ X
|| X <- ["tcp", "sctp", "udp"]]],
Pr <- ["" | [";protocol=" ++ X
|| X <- ["diameter","radius","tacacs+"]]],
Tr /= ";transport=udp"
orelse (Pr /= ";protocol=diameter" andalso Pr /= "")],
- ["aaa://diameter.se;transport=udp;protocol=diameter",
+ ["aaa://diameter.se:65536",
+ "aaa://diameter.se:-1",
+ "aaa://diameter.se;transport=udp;protocol=diameter",
"aaa://diameter.se;transport=udp",
"aaa://:3868",
"aaax://diameter.se",