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