From 23f4279f49ce84c8d0e96a4d4a1478b2ee9ec190 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 19 Apr 2018 11:44:46 +0200 Subject: Improve node allowed check * Move the node name check earlier * Check while still a list * Export allowed check function * Make allowed check function handle atom and list mixes --- lib/kernel/src/dist_util.erl | 75 +++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 28 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 781397e1ee..b325fc5456 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2017. All Rights Reserved. +%% Copyright Ericsson AB 1999-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ strict_order_flags/0, start_timer/1, setup_timer/2, reset_timer/1, cancel_timer/1, + is_allowed/2, shutdown/3, shutdown/4]). -import(error_logger,[error_msg/2]). @@ -182,7 +183,6 @@ handshake_other_started(#hs_data{request_type=ReqType, reject_flags=RejFlgs, require_flags=ReqFlgs}, check_dflags(HSData, EDF), - is_allowed(HSData), ?debug({"MD5 connection from ~p (V~p)~n", [Node, HSData#hs_data.other_version]}), mark_pending(HSData), @@ -199,21 +199,6 @@ handshake_other_started(OldHsData) when element(1,OldHsData) =:= hs_data -> handshake_other_started(convert_old_hsdata(OldHsData)). -%% -%% check if connecting node is allowed to connect -%% with allow-node-scheme -%% -is_allowed(#hs_data{other_node = Node, - allowed = Allowed} = HSData) -> - case lists:member(Node, Allowed) of - false when Allowed =/= [] -> - send_status(HSData, not_allowed), - error_msg("** Connection attempt from " - "disallowed node ~w ** ~n", [Node]), - ?shutdown2(Node, {is_allowed, not_allowed}); - _ -> true - end. - %% %% Check mandatory flags... %% @@ -642,24 +627,58 @@ send_challenge_ack(#hs_data{socket = Socket, f_send = FSend}, %% tcp_drv.c which used it to detect simultaneous connection %% attempts). %% -recv_name(#hs_data{socket = Socket, f_recv = Recv}) -> +recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) -> case Recv(Socket, 0, infinity) of - {ok,Data} -> - get_name(Data); + {ok, + [$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 + | OtherNode] = Data} -> + case is_valid_name(OtherNode) of + true -> + Flags = ?u32(Flag1, Flag2, Flag3, Flag4), + Version = ?u16(VersionA,VersionB), + is_allowed(HSData, Flags, OtherNode, Version); + false -> + ?shutdown(Data) + end; _ -> ?shutdown(no_node) end. -get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode] = Data) -> - case is_valid_name(OtherNode) of +%% +%% check if connecting node is allowed to connect +%% with allow-node-scheme +%% +is_allowed(#hs_data{allowed = []}, Flags, Node, Version) -> + {Flags,list_to_atom(Node),Version}; +is_allowed(#hs_data{allowed = Allowed} = HSData, Flags, Node, Version) -> + case is_allowed(Node, Allowed) of true -> - {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode), - ?u16(VersionA,VersionB)}; + {Flags,list_to_atom(Node),Version}; false -> - ?shutdown(Data) - end; -get_name(Data) -> - ?shutdown(Data). + send_status(HSData#hs_data{other_node = Node}, not_allowed), + error_msg("** Connection attempt from " + "disallowed node ~s ** ~n", [Node]), + ?shutdown2(Node, {is_allowed, not_allowed}) + end. + +is_allowed(_Node, []) -> + false; +is_allowed(Node, [AllowedNode|Allowed]) -> + case is_nodename_equal(Node, AllowedNode) of + true -> + true; + false -> + is_allowed(Node, Allowed) + end. + +is_nodename_equal(A, B) when is_atom(A), is_atom(B) -> + A =:= B; +is_nodename_equal(A, B) when is_atom(A) -> + is_nodename_equal(atom_to_list(A), B); +is_nodename_equal(A, B) when is_atom(B) -> + is_nodename_equal(A, atom_to_list(B)); +is_nodename_equal(A, B) when is_list(A), is_list(B) -> + A =:= B. is_valid_name(OtherNodeName) -> case string:lexemes(OtherNodeName,"@") of -- cgit v1.2.3 From 4c4d861792d79ac7773548c089b7a93bc2c72a51 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 20 Apr 2018 16:52:15 +0200 Subject: Open for host and node allow list --- lib/kernel/src/dist_util.erl | 81 ++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 22 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index b325fc5456..402d474c6d 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -30,7 +30,7 @@ strict_order_flags/0, start_timer/1, setup_timer/2, reset_timer/1, cancel_timer/1, - is_allowed/2, + is_node_name/1, split_node/1, is_allowed/2, shutdown/3, shutdown/4]). -import(error_logger,[error_msg/2]). @@ -632,7 +632,7 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) -> {ok, [$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode] = Data} -> - case is_valid_name(OtherNode) of + case is_node_name(OtherNode) of true -> Flags = ?u32(Flag1, Flag2, Flag3, Flag4), Version = ?u16(VersionA,VersionB), @@ -644,6 +644,31 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) -> ?shutdown(no_node) end. +is_node_name(OtherNodeName) -> + case string:split(OtherNodeName, "@") of + [Name,Host] -> + (not string:is_empty(Name)) + andalso (not string:is_empty(Host)); + _ -> + false + end. + +split_node(Node) -> + case string:split(listify_node(Node), "@") of + [Name,Host] = Split -> + case + (not string:is_empty(Name)) + andalso (not string:is_empty(Host)) + of + true -> + {Name,Host}; + false -> + Split + end; + Split -> + Split + end. + %% %% check if connecting node is allowed to connect %% with allow-node-scheme @@ -661,32 +686,44 @@ is_allowed(#hs_data{allowed = Allowed} = HSData, Flags, Node, Version) -> ?shutdown2(Node, {is_allowed, not_allowed}) end. +%% Allow Node on Allowed node list, and also if host part +%% of Node matches Allowed list item. The Allowed list +%% contains node names or host names. +%% is_allowed(_Node, []) -> false; +is_allowed(Node, [Node|_Allowed]) when is_atom(Node) -> + true; is_allowed(Node, [AllowedNode|Allowed]) -> - case is_nodename_equal(Node, AllowedNode) of - true -> - true; - false -> + case split_node(AllowedNode) of + {AllowedName,AllowedHost} -> + %% Allowed node name + case split_node(Node) of + {AllowedName,AllowedHost} -> + true; + _ -> + is_allowed(Node, Allowed) + end; + [AllowedHost] -> + %% Allowed host name + case split_node(Node) of + {_,AllowedHost} -> + %% Matching Host part + true; + [AllowedHost] -> + %% Host matches Host + true; + _ -> + is_allowed(Node, Allowed) + end; + _ -> is_allowed(Node, Allowed) end. -is_nodename_equal(A, B) when is_atom(A), is_atom(B) -> - A =:= B; -is_nodename_equal(A, B) when is_atom(A) -> - is_nodename_equal(atom_to_list(A), B); -is_nodename_equal(A, B) when is_atom(B) -> - is_nodename_equal(A, atom_to_list(B)); -is_nodename_equal(A, B) when is_list(A), is_list(B) -> - A =:= B. - -is_valid_name(OtherNodeName) -> - case string:lexemes(OtherNodeName,"@") of - [_OtherNodeName,_OtherNodeHost] -> - true; - _else -> - false - end. +listify_node(Atom) when is_atom(Atom) -> + atom_to_list(Atom); +listify_node(Node) when is_list(Node) -> + Node. publish_type(Flags) -> case Flags band ?DFLAG_PUBLISHED of -- cgit v1.2.3 From 5586959ed008c09141689f1e8865476150e48519 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 26 Apr 2018 09:37:24 +0200 Subject: Allow check for node name --- lib/kernel/src/dist_util.erl | 76 +++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 25 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 402d474c6d..ecc022b28d 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -645,7 +645,7 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) -> end. is_node_name(OtherNodeName) -> - case string:split(OtherNodeName, "@") of + case string:split(OtherNodeName, "@", all) of [Name,Host] -> (not string:is_empty(Name)) andalso (not string:is_empty(Host)); @@ -654,24 +654,32 @@ is_node_name(OtherNodeName) -> end. split_node(Node) -> - case string:split(listify_node(Node), "@") of - [Name,Host] = Split -> - case - (not string:is_empty(Name)) - andalso (not string:is_empty(Host)) - of + Split = string:split(listify(Node), "@", all), + case Split of + [Name,Host] -> + case string:is_empty(Name) of true -> - {Name,Host}; + Split; false -> - Split + case string:is_empty(Host) of + true -> + {name,Name}; + false -> + {node,Name,Host} + end end; - Split -> - Split + [Host] -> + case string:is_empty(Host) of + true -> + Split; + false -> + {host,Host} + end end. -%% -%% check if connecting node is allowed to connect -%% with allow-node-scheme +%% Check if connecting node is allowed to connect +%% with allow-node-scheme. An empty allowed list +%% allows all nodes. %% is_allowed(#hs_data{allowed = []}, Flags, Node, Version) -> {Flags,list_to_atom(Node),Version}; @@ -686,43 +694,61 @@ is_allowed(#hs_data{allowed = Allowed} = HSData, Flags, Node, Version) -> ?shutdown2(Node, {is_allowed, not_allowed}) end. -%% Allow Node on Allowed node list, and also if host part -%% of Node matches Allowed list item. The Allowed list -%% contains node names or host names. +%% The allowed list can contain node names, host names +%% or names before '@', in atom or list form: +%% [node@host.example.org, "host.example.org", "node@"]. +%% An empty allowed list allows no nodes. +%% +%% Allow a node that matches any entry in the allowed list. +%% Also allow allowed entries as node to match, not from +%% this module; here the node has to be a valid name. %% is_allowed(_Node, []) -> false; -is_allowed(Node, [Node|_Allowed]) when is_atom(Node) -> +is_allowed(Node, [Node|_Allowed]) -> + %% Just an optimization true; is_allowed(Node, [AllowedNode|Allowed]) -> case split_node(AllowedNode) of - {AllowedName,AllowedHost} -> + {node,AllowedName,AllowedHost} -> %% Allowed node name case split_node(Node) of - {AllowedName,AllowedHost} -> + {node,AllowedName,AllowedHost} -> true; _ -> is_allowed(Node, Allowed) end; - [AllowedHost] -> + {host,AllowedHost} -> %% Allowed host name case split_node(Node) of - {_,AllowedHost} -> + {node,_,AllowedHost} -> %% Matching Host part true; - [AllowedHost] -> + {host,AllowedHost} -> %% Host matches Host true; _ -> is_allowed(Node, Allowed) end; + {name,AllowedName} -> + %% Allowed name before '@' + case split_node(Node) of + {node,AllowedName,_} -> + %% Matching Name part + true; + {name,AllowedName} -> + %% Name matches Name + true; + _ -> + is_allowed(Node, Allowed) + end; _ -> is_allowed(Node, Allowed) end. -listify_node(Atom) when is_atom(Atom) -> +listify(Atom) when is_atom(Atom) -> atom_to_list(Atom); -listify_node(Node) when is_list(Node) -> +listify(Node) when is_list(Node) -> Node. publish_type(Flags) -> -- cgit v1.2.3