1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22-module(inet_tls_dist).
23
24-export([childspecs/0]).
25-export([listen/1, accept/1, accept_connection/5,
26	 setup/5, close/1, select/1, is_node_name/1]).
27
28%% Generalized dist API
29-export([gen_listen/2, gen_accept/2, gen_accept_connection/6,
30	 gen_setup/6, gen_close/2, gen_select/2]).
31
32-export([nodelay/0]).
33
34-export([verify_client/3, cert_nodes/1]).
35
36-export([dbg/0]). % Debug
37
38-include_lib("kernel/include/net_address.hrl").
39-include_lib("kernel/include/dist.hrl").
40-include_lib("kernel/include/dist_util.hrl").
41-include_lib("public_key/include/public_key.hrl").
42
43-include("ssl_api.hrl").
44
45%% -------------------------------------------------------------------------
46
47childspecs() ->
48    {ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
49	   permanent, infinity, supervisor, [ssl_dist_sup]}]}.
50
51select(Node) ->
52    gen_select(inet_tcp, Node).
53
54gen_select(Driver, Node) ->
55    case dist_util:split_node(Node) of
56        {node,_,Host} ->
57	    case Driver:getaddr(Host) of
58		{ok, _} -> true;
59		_ -> false
60	    end;
61        _ ->
62            false
63    end.
64
65%% -------------------------------------------------------------------------
66
67is_node_name(Node) ->
68    dist_util:is_node_name(Node).
69
70%% -------------------------------------------------------------------------
71
72hs_data_common(#sslsocket{pid = [_, DistCtrl|_]} = SslSocket) ->
73    #hs_data{
74       f_send =
75           fun (_Ctrl, Packet) ->
76                   f_send(SslSocket, Packet)
77           end,
78       f_recv =
79           fun (_, Length, Timeout) ->
80                   f_recv(SslSocket, Length, Timeout)
81           end,
82       f_setopts_pre_nodeup =
83           fun (Ctrl) when Ctrl == DistCtrl ->
84                   f_setopts_pre_nodeup(SslSocket)
85           end,
86       f_setopts_post_nodeup =
87           fun (Ctrl) when Ctrl == DistCtrl ->
88%%%                   sys:trace(Ctrl, true),
89                   f_setopts_post_nodeup(SslSocket)
90           end,
91       f_getll =
92           fun (Ctrl) when Ctrl == DistCtrl ->
93                   f_getll(DistCtrl)
94           end,
95       f_address =
96           fun (Ctrl, Node) when Ctrl == DistCtrl ->
97                   f_address(SslSocket, Node)
98           end,
99       mf_tick =
100           fun (Ctrl) when Ctrl == DistCtrl ->
101                   mf_tick(DistCtrl)
102           end,
103       mf_getstat =
104           fun (Ctrl) when Ctrl == DistCtrl ->
105                   mf_getstat(SslSocket)
106           end,
107       mf_setopts =
108           fun (Ctrl, Opts) when Ctrl == DistCtrl ->
109                   mf_setopts(SslSocket, Opts)
110           end,
111       mf_getopts =
112           fun (Ctrl, Opts) when Ctrl == DistCtrl ->
113                   mf_getopts(SslSocket, Opts)
114           end,
115       f_handshake_complete =
116           fun (Ctrl, Node, DHandle) when Ctrl == DistCtrl ->
117                   f_handshake_complete(DistCtrl, Node, DHandle)
118           end}.
119
120f_send(SslSocket, Packet) ->
121    ssl:send(SslSocket, Packet).
122
123f_recv(SslSocket, Length, Timeout) ->
124    case ssl:recv(SslSocket, Length, Timeout) of
125        {ok, Bin} when is_binary(Bin) ->
126            {ok, binary_to_list(Bin)};
127        Other ->
128            Other
129    end.
130
131f_setopts_pre_nodeup(_SslSocket) ->
132    ok.
133
134f_setopts_post_nodeup(_SslSocket) ->
135    ok.
136
137f_getll(DistCtrl) ->
138    {ok, DistCtrl}.
139
140f_address(SslSocket, Node) ->
141    case ssl:peername(SslSocket) of
142        {ok, Address} ->
143            case dist_util:split_node(Node) of
144                {node,_,Host} ->
145                    #net_address{
146                       address=Address, host=Host,
147                       protocol=tls, family=inet};
148                _ ->
149                    {error, no_node}
150            end
151    end.
152
153mf_tick(DistCtrl) ->
154    DistCtrl ! tick,
155    ok.
156
157mf_getstat(SslSocket) ->
158    case ssl:getstat(
159           SslSocket, [recv_cnt, send_cnt, send_pend]) of
160        {ok, Stat} ->
161            split_stat(Stat,0,0,0);
162        Error ->
163            Error
164    end.
165
166mf_setopts(SslSocket, Opts) ->
167    case setopts_filter(Opts) of
168        [] ->
169            ssl:setopts(SslSocket, Opts);
170        Opts1 ->
171            {error, {badopts,Opts1}}
172    end.
173
174mf_getopts(SslSocket, Opts) ->
175    ssl:getopts(SslSocket, Opts).
176
177f_handshake_complete(DistCtrl, Node, DHandle) ->
178    tls_sender:dist_handshake_complete(DistCtrl, Node, DHandle).
179
180setopts_filter(Opts) ->
181    [Opt || {K,_} = Opt <- Opts,
182            K =:= active orelse K =:= deliver orelse K =:= packet].
183
184split_stat([{recv_cnt, R}|Stat], _, W, P) ->
185    split_stat(Stat, R, W, P);
186split_stat([{send_cnt, W}|Stat], R, _, P) ->
187    split_stat(Stat, R, W, P);
188split_stat([{send_pend, P}|Stat], R, W, _) ->
189    split_stat(Stat, R, W, P);
190split_stat([], R, W, P) ->
191    {ok, R, W, P}.
192
193%% -------------------------------------------------------------------------
194
195listen(Name) ->
196    gen_listen(inet_tcp, Name).
197
198gen_listen(Driver, Name) ->
199    case inet_tcp_dist:gen_listen(Driver, Name) of
200        {ok, {Socket, Address, Creation}} ->
201            inet:setopts(Socket, [{packet, 4}]),
202            {ok, {Socket, Address#net_address{protocol=tls}, Creation}};
203        Other ->
204            Other
205    end.
206
207%% -------------------------------------------------------------------------
208
209accept(Listen) ->
210    gen_accept(inet_tcp, Listen).
211
212gen_accept(Driver, Listen) ->
213    Kernel = self(),
214    monitor_pid(
215      spawn_opt(
216        fun () ->
217                accept_loop(Driver, Listen, Kernel)
218        end,
219        [link, {priority, max}])).
220
221accept_loop(Driver, Listen, Kernel) ->
222    case Driver:accept(Listen) of
223        {ok, Socket} ->
224	    case check_ip(Driver, Socket) of
225                true ->
226                    accept_loop(Driver, Listen, Kernel, Socket);
227                {false,IP} ->
228		    error_logger:error_msg(
229                      "** Connection attempt from "
230                      "disallowed IP ~w ** ~n", [IP]),
231		    ?shutdown2(no_node, trace({disallowed, IP}))
232	    end;
233	Error ->
234	    exit(trace(Error))
235    end.
236
237accept_loop(Driver, Listen, Kernel, Socket) ->
238    Opts = setup_verify_client(Socket, get_ssl_options(server)),
239    wait_for_code_server(),
240    case
241        ssl:handshake(
242          Socket,
243          trace([{active, false},{packet, 4}|Opts]),
244          net_kernel:connecttime())
245    of
246        {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
247            trace(
248              Kernel !
249                  {accept, self(), DistCtrl,
250                   Driver:family(), tls}),
251            receive
252                {Kernel, controller, Pid} ->
253                    ok = ssl:controlling_process(SslSocket, Pid),
254                    trace(
255                      Pid ! {self(), controller});
256                {Kernel, unsupported_protocol} ->
257                    exit(trace(unsupported_protocol))
258            end,
259            accept_loop(Driver, Listen, Kernel);
260        {error, {options, _}} = Error ->
261            %% Bad options: that's probably our fault.
262            %% Let's log that.
263            error_logger:error_msg(
264              "Cannot accept TLS distribution connection: ~s~n",
265              [ssl:format_error(Error)]),
266            gen_tcp:close(Socket),
267            exit(trace(Error));
268        Other ->
269            gen_tcp:close(Socket),
270            exit(trace(Other))
271    end.
272
273
274%% {verify_fun,{fun ?MODULE:verify_client/3,_}} is used
275%% as a configuration marker that verify_client/3 shall be used.
276%%
277%% Replace the State in the first occurence of
278%% {verify_fun,{fun ?MODULE:verify_client/3,State}}
279%% and remove the rest.
280%% The inserted state is not accesible from a configuration file
281%% since it is dynamic and connection dependent.
282%%
283setup_verify_client(Socket, Opts) ->
284    setup_verify_client(Socket, Opts, true, []).
285%%
286setup_verify_client(_Socket, [], _, OptsR) ->
287    lists:reverse(OptsR);
288setup_verify_client(Socket, [Opt|Opts], First, OptsR) ->
289    case Opt of
290        {verify_fun,{Fun,_}} ->
291            case Fun =:= fun ?MODULE:verify_client/3 of
292                true ->
293                    if
294                        First ->
295                            case inet:peername(Socket) of
296                                {ok,{PeerIP,_Port}} ->
297                                    {ok,Allowed} = net_kernel:allowed(),
298                                    AllowedHosts = allowed_hosts(Allowed),
299                                    setup_verify_client(
300                                      Socket, Opts, false,
301                                      [{verify_fun,
302                                        {Fun, {AllowedHosts,PeerIP}}}
303                                       |OptsR]);
304                                {error,Reason} ->
305                                    exit(trace({no_peername,Reason}))
306                            end;
307                        true ->
308                            setup_verify_client(
309                              Socket, Opts, First, OptsR)
310                    end;
311                false ->
312                    setup_verify_client(
313                      Socket, Opts, First, [Opt|OptsR])
314            end;
315        _ ->
316            setup_verify_client(Socket, Opts, First, [Opt|OptsR])
317    end.
318
319allowed_hosts(Allowed) ->
320    lists:usort(allowed_node_hosts(Allowed)).
321%%
322allowed_node_hosts([]) -> [];
323allowed_node_hosts([Node|Allowed]) ->
324    case dist_util:split_node(Node) of
325        {node,_,Host} ->
326            [Host|allowed_node_hosts(Allowed)];
327        {host,Host} ->
328            [Host|allowed_node_hosts(Allowed)];
329        _ ->
330            allowed_node_hosts(Allowed)
331    end.
332
333%% Same as verify_peer but check cert host names for
334%% peer IP address
335verify_client(_, {bad_cert,_} = Reason, _) ->
336    {fail,Reason};
337verify_client(_, {extension,_}, S) ->
338    {unknown,S};
339verify_client(_, valid, S) ->
340    {valid,S};
341verify_client(_, valid_peer, {[],_} = S) ->
342    %% Allow all hosts
343    {valid,S};
344verify_client(PeerCert, valid_peer, {AllowedHosts,PeerIP} = S) ->
345    case
346        public_key:pkix_verify_hostname(
347          PeerCert,
348          [{ip,PeerIP}|[{dns_id,Host} || Host <- AllowedHosts]])
349    of
350        true ->
351            {valid,S};
352        false ->
353            {fail,cert_no_hostname_nor_ip_match}
354    end.
355
356
357wait_for_code_server() ->
358    %% This is an ugly hack.  Upgrading a socket to TLS requires the
359    %% crypto module to be loaded.  Loading the crypto module triggers
360    %% its on_load function, which calls code:priv_dir/1 to find the
361    %% directory where its NIF library is.  However, distribution is
362    %% started earlier than the code server, so the code server is not
363    %% necessarily started yet, and code:priv_dir/1 might fail because
364    %% of that, if we receive an incoming connection on the
365    %% distribution port early enough.
366    %%
367    %% If the on_load function of a module fails, the module is
368    %% unloaded, and the function call that triggered loading it fails
369    %% with 'undef', which is rather confusing.
370    %%
371    %% Thus, the accept process will terminate, and be
372    %% restarted by ssl_dist_sup.  However, it won't have any memory
373    %% of being asked by net_kernel to listen for incoming
374    %% connections.  Hence, the node will believe that it's open for
375    %% distribution, but it actually isn't.
376    %%
377    %% So let's avoid that by waiting for the code server to start.
378    case whereis(code_server) of
379	undefined ->
380	    timer:sleep(10),
381	    wait_for_code_server();
382	Pid when is_pid(Pid) ->
383	    ok
384    end.
385
386%% -------------------------------------------------------------------------
387
388accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
389    gen_accept_connection(
390      inet_tcp, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime).
391
392gen_accept_connection(
393  Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
394    Kernel = self(),
395    monitor_pid(
396      spawn_opt(
397        fun() ->
398                do_accept(
399                  Driver, AcceptPid, DistCtrl,
400                  MyNode, Allowed, SetupTime, Kernel)
401        end,
402        [link, {priority, max}])).
403
404do_accept(
405  _Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime, Kernel) ->
406    {ok, SslSocket} = tls_sender:dist_tls_socket(DistCtrl),
407    receive
408	{AcceptPid, controller} ->
409	    Timer = dist_util:start_timer(SetupTime),
410            NewAllowed = allowed_nodes(SslSocket, Allowed),
411            HSData0 = hs_data_common(SslSocket),
412            HSData =
413                HSData0#hs_data{
414                  kernel_pid = Kernel,
415                  this_node = MyNode,
416                  socket = DistCtrl,
417                  timer = Timer,
418                  this_flags = 0,
419                  allowed = NewAllowed},
420            link(DistCtrl),
421            dist_util:handshake_other_started(trace(HSData))
422    end.
423
424allowed_nodes(_SslSocket, []) ->
425    %% Allow all
426    [];
427allowed_nodes(SslSocket, Allowed) ->
428    case ssl:peercert(SslSocket) of
429        {ok,PeerCertDER} ->
430            case ssl:peername(SslSocket) of
431                {ok,{PeerIP,_Port}} ->
432                    PeerCert =
433                        public_key:pkix_decode_cert(PeerCertDER, otp),
434                    case
435                        allowed_nodes(
436                          PeerCert, allowed_hosts(Allowed), PeerIP)
437                    of
438                        [] ->
439                            error_logger:error_msg(
440                              "** Connection attempt from "
441                              "disallowed node(s) ~p ** ~n", [PeerIP]),
442                            ?shutdown2(
443                               PeerIP, trace({is_allowed, not_allowed}));
444                        AllowedNodes ->
445                            AllowedNodes
446                    end;
447                Error1 ->
448                    ?shutdown2(no_peer_ip, trace(Error1))
449            end;
450        {error,no_peercert} ->
451            Allowed;
452        Error2 ->
453            ?shutdown2(no_peer_cert, trace(Error2))
454    end.
455
456allowed_nodes(PeerCert, [], PeerIP) ->
457    case public_key:pkix_verify_hostname(PeerCert, [{ip,PeerIP}]) of
458        true ->
459            Host = inet:ntoa(PeerIP),
460            true = is_list(Host),
461            [Host];
462        false ->
463            []
464    end;
465allowed_nodes(PeerCert, [Node|Allowed], PeerIP) ->
466    case dist_util:split_node(Node) of
467        {node,_,Host} ->
468            allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host);
469        {host,Host} ->
470            allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host);
471        _ ->
472            allowed_nodes(PeerCert, Allowed, PeerIP)
473    end.
474
475allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host) ->
476    case public_key:pkix_verify_hostname(PeerCert, [{dns_id,Host}]) of
477        true ->
478            [Node|allowed_nodes(PeerCert, Allowed, PeerIP)];
479        false ->
480            allowed_nodes(PeerCert, Allowed, PeerIP)
481    end.
482
483setup(Node, Type, MyNode, LongOrShortNames, SetupTime) ->
484    gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime).
485
486gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
487    Kernel = self(),
488    monitor_pid(
489      spawn_opt(setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime),
490                [link, {priority, max}])).
491
492-spec setup_fun(_,_,_,_,_,_,_) -> fun(() -> no_return()).
493setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
494    fun() ->
495            do_setup(
496              Driver, Kernel, Node, Type,
497              MyNode, LongOrShortNames, SetupTime)
498    end.
499
500
501-spec do_setup(_,_,_,_,_,_,_) -> no_return().
502do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
503    {Name, Address} = split_node(Driver, Node, LongOrShortNames),
504    ErlEpmd = net_kernel:epmd_module(),
505    {ARMod, ARFun} = get_address_resolver(ErlEpmd, Driver),
506    Timer = trace(dist_util:start_timer(SetupTime)),
507    case ARMod:ARFun(Name,Address,Driver:family()) of
508    {ok, Ip, TcpPort, Version} ->
509        do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer);
510	{ok, Ip} ->
511	    case ErlEpmd:port_please(Name, Ip) of
512		{port, TcpPort, Version} ->
513                do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer);
514		Other ->
515		    ?shutdown2(
516                       Node,
517                       trace(
518                         {port_please_failed, ErlEpmd, Name, Ip, Other}))
519	    end;
520	Other ->
521	    ?shutdown2(
522               Node,
523               trace({getaddr_failed, Driver, Address, Other}))
524    end.
525
526-spec do_setup_connect(_,_,_,_,_,_,_,_,_,_) -> no_return().
527
528do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer) ->
529    Opts =  trace(connect_options(get_ssl_options(client))),
530    dist_util:reset_timer(Timer),
531    case ssl:connect(
532        Address, TcpPort,
533        [binary, {active, false}, {packet, 4},
534            Driver:family(), nodelay()] ++ Opts,
535        net_kernel:connecttime()) of
536    {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
537            _ = monitor_pid(DistCtrl),
538            ok = ssl:controlling_process(SslSocket, self()),
539            HSData0 = hs_data_common(SslSocket),
540        HSData =
541                HSData0#hs_data{
542                kernel_pid = Kernel,
543                other_node = Node,
544                this_node = MyNode,
545                socket = DistCtrl,
546                timer = Timer,
547                this_flags = 0,
548                other_version = Version,
549                request_type = Type},
550            link(DistCtrl),
551    dist_util:handshake_we_started(trace(HSData));
552    Other ->
553    %% Other Node may have closed since
554    %% port_please !
555    ?shutdown2(
556            Node,
557            trace(
558                {ssl_connect_failed, Ip, TcpPort, Other}))
559    end.
560
561close(Socket) ->
562    gen_close(inet, Socket).
563
564gen_close(Driver, Socket) ->
565    trace(Driver:close(Socket)).
566
567
568%% ------------------------------------------------------------
569%% Determine if EPMD module supports address resolving. Default
570%% is to use inet_tcp:getaddr/2.
571%% ------------------------------------------------------------
572get_address_resolver(EpmdModule, _Driver) ->
573    case erlang:function_exported(EpmdModule, address_please, 3) of
574        true -> {EpmdModule, address_please};
575        _    -> {erl_epmd, address_please}
576    end.
577
578%% ------------------------------------------------------------
579%% Do only accept new connection attempts from nodes at our
580%% own LAN, if the check_ip environment parameter is true.
581%% ------------------------------------------------------------
582check_ip(Driver, Socket) ->
583    case application:get_env(check_ip) of
584	{ok, true} ->
585	    case get_ifs(Socket) of
586		{ok, IFs, IP} ->
587		    check_ip(Driver, IFs, IP);
588		Other ->
589		    ?shutdown2(
590                       no_node, trace({check_ip_failed, Socket, Other}))
591	    end;
592	_ ->
593	    true
594    end.
595
596check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) ->
597    case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of
598	{M, M} -> true;
599	_      -> check_ip(IFs, PeerIP)
600    end;
601check_ip(_Driver, [], PeerIP) ->
602    {false, PeerIP}.
603
604get_ifs(Socket) ->
605    case inet:peername(Socket) of
606	{ok, {IP, _}} ->
607            %% XXX this is seriously broken for IPv6
608	    case inet:getif(Socket) of
609		{ok, IFs} -> {ok, IFs, IP};
610		Error     -> Error
611	    end;
612	Error ->
613	    Error
614    end.
615
616
617%% Look in Extensions, in all subjectAltName:s
618%% to find node names in this certificate.
619%% Host names are picked up as a subjectAltName containing
620%% a dNSName, and the first subjectAltName containing
621%% a commonName is the node name.
622%%
623cert_nodes(
624  #'OTPCertificate'{
625     tbsCertificate = #'OTPTBSCertificate'{extensions = Extensions}}) ->
626    parse_extensions(Extensions).
627
628
629parse_extensions(Extensions) when is_list(Extensions) ->
630    parse_extensions(Extensions, [], []);
631parse_extensions(asn1_NOVALUE) ->
632    undefined. % Allow all nodes
633%%
634parse_extensions([], [], []) ->
635    undefined; % Allow all nodes
636parse_extensions([], Hosts, []) ->
637    lists:reverse(Hosts);
638parse_extensions([], [], Names) ->
639    [Name ++ "@" || Name <- lists:reverse(Names)];
640parse_extensions([], Hosts, Names) ->
641    [Name ++ "@" ++ Host ||
642        Host <- lists:reverse(Hosts),
643        Name <- lists:reverse(Names)];
644parse_extensions(
645  [#'Extension'{
646      extnID = ?'id-ce-subjectAltName',
647      extnValue = AltNames}
648   |Extensions],
649  Hosts, Names) ->
650    case parse_subject_altname(AltNames) of
651        none ->
652            parse_extensions(Extensions, Hosts, Names);
653        {host,Host} ->
654            parse_extensions(Extensions, [Host|Hosts], Names);
655        {name,Name} ->
656            parse_extensions(Extensions, Hosts, [Name|Names])
657    end;
658parse_extensions([_|Extensions], Hosts, Names) ->
659    parse_extensions(Extensions, Hosts, Names).
660
661parse_subject_altname([]) ->
662    none;
663parse_subject_altname([{dNSName,Host}|_AltNames]) ->
664    {host,Host};
665parse_subject_altname(
666  [{directoryName,{rdnSequence,[Rdn|_]}}|AltNames]) ->
667    %%
668    %% XXX Why is rdnSequence a sequence?
669    %% Should we parse all members?
670    %%
671    case parse_rdn(Rdn) of
672        none ->
673            parse_subject_altname(AltNames);
674        Name ->
675            {name,Name}
676    end;
677parse_subject_altname([_|AltNames]) ->
678    parse_subject_altname(AltNames).
679
680
681parse_rdn([]) ->
682    none;
683parse_rdn(
684  [#'AttributeTypeAndValue'{
685     type = ?'id-at-commonName',
686     value = {utf8String,CommonName}}|_]) ->
687    unicode:characters_to_list(CommonName);
688parse_rdn([_|Rdn]) ->
689    parse_rdn(Rdn).
690
691
692%% If Node is illegal terminate the connection setup!!
693split_node(Driver, Node, LongOrShortNames) ->
694    case dist_util:split_node(Node) of
695        {node, Name, Host} ->
696	    check_node(Driver, Node, Name, Host, LongOrShortNames);
697	{host, _} ->
698	    error_logger:error_msg(
699              "** Nodename ~p illegal, no '@' character **~n",
700              [Node]),
701	    ?shutdown2(Node, trace({illegal_node_n@me, Node}));
702	_ ->
703	    error_logger:error_msg(
704              "** Nodename ~p illegal **~n", [Node]),
705	    ?shutdown2(Node, trace({illegal_node_name, Node}))
706    end.
707
708check_node(Driver, Node, Name, Host, LongOrShortNames) ->
709    case string:split(Host, ".", all) of
710	[_] when LongOrShortNames =:= longnames ->
711	    case Driver:parse_address(Host) of
712		{ok, _} ->
713		    {Name, Host};
714		_ ->
715		    error_logger:error_msg(
716                      "** System running to use "
717                      "fully qualified hostnames **~n"
718                      "** Hostname ~s is illegal **~n",
719                      [Host]),
720		    ?shutdown2(Node, trace({not_longnames, Host}))
721	    end;
722	[_,_|_] when LongOrShortNames =:= shortnames ->
723	    error_logger:error_msg(
724              "** System NOT running to use "
725              "fully qualified hostnames **~n"
726              "** Hostname ~s is illegal **~n",
727              [Host]),
728	    ?shutdown2(Node, trace({not_shortnames, Host}));
729	_ ->
730	    {Name, Host}
731    end.
732
733%% -------------------------------------------------------------------------
734
735connect_options(Opts) ->
736    case application:get_env(kernel, inet_dist_connect_options) of
737	{ok,ConnectOpts} ->
738	    lists:ukeysort(1, ConnectOpts ++ Opts);
739	_ ->
740	    Opts
741    end.
742
743%% we may not always want the nodelay behaviour
744%% for performance reasons
745nodelay() ->
746    case application:get_env(kernel, dist_nodelay) of
747	undefined ->
748	    {nodelay, true};
749	{ok, true} ->
750	    {nodelay, true};
751	{ok, false} ->
752	    {nodelay, false};
753	_ ->
754	    {nodelay, true}
755    end.
756
757
758get_ssl_options(Type) ->
759    try ets:lookup(ssl_dist_opts, Type) of
760        [{Type, Opts}] ->
761            [{erl_dist, true} | Opts];
762        _ ->
763            get_ssl_dist_arguments(Type)
764    catch
765        error:badarg ->
766            get_ssl_dist_arguments(Type)
767    end.
768
769get_ssl_dist_arguments(Type) ->
770    case init:get_argument(ssl_dist_opt) of
771	{ok, Args} ->
772	    [{erl_dist, true} | ssl_options(Type, lists:append(Args))];
773	_ ->
774	    [{erl_dist, true}]
775    end.
776
777
778ssl_options(_Type, []) ->
779    [];
780ssl_options(client, ["client_" ++ Opt, Value | T] = Opts) ->
781    ssl_options(client, T, Opts, Opt, Value);
782ssl_options(server, ["server_" ++ Opt, Value | T] = Opts) ->
783    ssl_options(server, T, Opts, Opt, Value);
784ssl_options(Type, [_Opt, _Value | T]) ->
785    ssl_options(Type, T).
786%%
787ssl_options(Type, T, Opts, Opt, Value) ->
788    case ssl_option(Type, Opt) of
789        error ->
790            error(malformed_ssl_dist_opt, [Type, Opts]);
791        Fun ->
792            [{list_to_atom(Opt), Fun(Value)}|ssl_options(Type, T)]
793    end.
794
795ssl_option(server, Opt) ->
796    case Opt of
797        "dhfile" -> fun listify/1;
798        "fail_if_no_peer_cert" -> fun atomize/1;
799        _ -> ssl_option(client, Opt)
800    end;
801ssl_option(client, Opt) ->
802    case Opt of
803        "certfile" -> fun listify/1;
804        "cacertfile" -> fun listify/1;
805        "keyfile" -> fun listify/1;
806        "password" -> fun listify/1;
807        "verify" -> fun atomize/1;
808        "verify_fun" -> fun verify_fun/1;
809        "crl_check" -> fun atomize/1;
810        "crl_cache" -> fun termify/1;
811        "reuse_sessions" -> fun atomize/1;
812        "secure_renegotiate" -> fun atomize/1;
813        "depth" -> fun erlang:list_to_integer/1;
814        "hibernate_after" -> fun erlang:list_to_integer/1;
815        "ciphers" -> fun listify/1;
816        _ -> error
817    end.
818
819listify(List) when is_list(List) ->
820    List.
821
822atomize(List) when is_list(List) ->
823    list_to_atom(List);
824atomize(Atom) when is_atom(Atom) ->
825    Atom.
826
827termify(String) when is_list(String) ->
828    {ok, Tokens, _} = erl_scan:string(String ++ "."),
829    {ok, Term} = erl_parse:parse_term(Tokens),
830    Term.
831
832verify_fun(Value) ->
833    case termify(Value) of
834	{Mod, Func, State} when is_atom(Mod), is_atom(Func) ->
835	    Fun = fun Mod:Func/3,
836	    {Fun, State};
837	_ ->
838	    error(malformed_ssl_dist_opt, [Value])
839    end.
840
841%% -------------------------------------------------------------------------
842
843%% Trace point
844trace(Term) -> Term.
845
846%% Keep an eye on distribution Pid:s we know of
847monitor_pid(Pid) ->
848    %%spawn(
849    %%  fun () ->
850    %%          MRef = erlang:monitor(process, Pid),
851    %%          receive
852    %%              {'DOWN', MRef, _, _, normal} ->
853    %%                  error_logger:error_report(
854    %%                    [dist_proc_died,
855    %%                     {reason, normal},
856    %%                     {pid, Pid}]);
857    %%              {'DOWN', MRef, _, _, Reason} ->
858    %%                  error_logger:info_report(
859    %%                    [dist_proc_died,
860    %%                     {reason, Reason},
861    %%                     {pid, Pid}])
862    %%          end
863    %%  end),
864    Pid.
865
866dbg() ->
867    dbg:stop(),
868    dbg:tracer(),
869    dbg:p(all, c),
870    dbg:tpl(?MODULE, cx),
871    dbg:tpl(erlang, dist_ctrl_get_data_notification, cx),
872    dbg:tpl(erlang, dist_ctrl_get_data, cx),
873    dbg:tpl(erlang, dist_ctrl_put_data, cx),
874    ok.
875