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