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