68
75
connect(Socket, SslOptions) when is_port(Socket) ->
69
76
connect(Socket, SslOptions, infinity).
71
connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
78
connect(Socket, SslOptions0, Timeout) when is_port(Socket) ->
72
79
EmulatedOptions = emulated_options(),
73
{ok, Inetvalues} = inet:getopts(Socket, EmulatedOptions),
80
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
74
81
inet:setopts(Socket, internal_inet_values()),
75
try handle_options(Inetvalues ++ SslOptions, client) of
78
handle_transport_protocol(Options0),
82
try handle_options(SslOptions0 ++ InetValues, client) of
83
{ok, #config{cb=CbInfo, ssl=SslOptions, emulated=EmOpts}} ->
79
84
case inet:peername(Socket) of
80
85
{ok, {Address, Port}} ->
81
86
ssl_connection:connect(Address, Port, Socket,
82
ssl_connection_options(Options),
88
self(), CbInfo, Timeout);
138
143
transport_accept(ListenSocket) ->
139
144
transport_accept(ListenSocket, infinity).
141
transport_accept(#sslsocket{pid = {ListenSocket, Options0},
146
transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}},
142
147
fd = new_ssl} = SslSocket, Timeout) ->
143
{{CbModule, _, _} = CbInfo, {SSlOpts, EmOpts, _}} =
144
handle_transport_protocol(Options0),
149
%% The setopt could have been invoked on the listen socket
150
%% and options should be inherited.
151
EmOptions = emulated_options(),
152
{ok, InetValues} = inet:getopts(ListenSocket, EmOptions),
153
{CbModule,_,_} = CbInfo,
145
154
{ok, Socket} = CbModule:accept(ListenSocket, Timeout),
155
inet:setopts(Socket, internal_inet_values()),
146
156
{ok, Port} = inet:port(Socket),
147
157
case ssl_connection_sup:start_child([server, "localhost", Port, Socket,
148
{SSlOpts, EmOpts}, self(),
158
{SslOpts, socket_options(InetValues)}, self(),
151
161
CbModule:controlling_process(Socket, Pid),
193
203
ensure_old_ssl_started(),
194
204
ssl_broker:ssl_accept(Socket, Timeout).
196
ssl_accept(ListenSocket, SslOptions, Timeout) when is_port(ListenSocket) ->
197
EmulatedOptions = emulated_options(),
198
{ok, Inetvalues} = inet:getopts(ListenSocket, EmulatedOptions),
199
inet:setopts(ListenSocket, internal_inet_values()),
200
try handle_options(Inetvalues ++ SslOptions, server) of
202
{{_, _, _} = CbInfo, {SSlOpts, EmOpts, _}} =
203
handle_transport_protocol(Options),
204
{ok, Port} = inet:port(ListenSocket),
205
ssl_connection:accept(Port, ListenSocket,
206
{SSlOpts, EmOpts}, self(), CbInfo, Timeout)
206
ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
207
EmulatedOptions = emulated_options(),
208
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
209
inet:setopts(Socket, internal_inet_values()),
210
try handle_options(SslOptions ++ InetValues, server) of
211
{ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} ->
212
{ok, Port} = inet:port(Socket),
213
ssl_connection:accept(Port, Socket,
215
self(), CbInfo, Timeout)
217
Error = {error, _Reason} -> Error
212
220
%%--------------------------------------------------------------------
434
441
%%%--------------------------------------------------------------------
435
442
new_connect(Address, Port, Options, Timeout) when is_list(Options) ->
436
443
try handle_options(Options, client) of
438
do_new_connect(Address, Port, NewOptions, Timeout)
445
do_new_connect(Address,Port,Config,Timeout)
444
do_new_connect(Address, Port, Options0, Timeout) ->
445
{{CbModule, _, _} = CbInfo, Options} =
446
handle_transport_protocol(Options0),
447
try CbModule:connect(Address, Port,
448
connect_options(Options), Timeout) of
451
do_new_connect(Address, Port,
452
#config{cb=CbInfo, inet_user=UserOpts, ssl=SslOpts,
453
emulated=EmOpts,inet_ssl=SocketOpts},
455
{CbModule, _, _} = CbInfo,
456
try CbModule:connect(Address, Port, SocketOpts, Timeout) of
450
ssl_connection:connect(Address, Port, Socket,
451
ssl_connection_options(Options), self(),
458
ssl_connection:connect(Address, Port, Socket, {SslOpts,EmOpts},
459
self(), CbInfo, Timeout);
453
460
{error, Reason} ->
456
463
exit:{function_clause, _} ->
459
{error,{eoptions, {inet_options, connect_options(Options)}}}
464
{error, {eoptions, {cb_info, CbInfo}}};
466
{error,{eoptions, {inet_options, UserOpts}}}
463
handle_transport_protocol({SSL, Emulated, Options0}) ->
465
proplists:get_value(cb_info, Options0, {gen_tcp, tcp, tcp_closed}),
466
Options = proplists:delete(cb_info, Options0),
467
{CbInfo, {SSL, Emulated, Options}}.
469
469
old_connect(Address, Port, Options, Timeout) ->
470
470
ensure_old_ssl_started(),
471
471
{ok, Pid} = ssl_broker:start_broker(connector),
472
472
ssl_broker:connect(Pid, Address, Port, Options, Timeout).
474
474
new_listen(Port, Options0) ->
475
try handle_options(Options0, server) of
478
handle_transport_protocol(Options1),
479
new_listen(CbInfo, Port, Options)
476
{ok, Config} = handle_options(Options0, server),
477
#config{cb={CbModule, _, _},inet_user=Options} = Config,
478
case CbModule:listen(Port, Options) of
479
{ok, ListenSocket} ->
480
{ok, #sslsocket{pid = {ListenSocket, Config}, fd = new_ssl}};
485
new_listen({CbModule, _, _} = CbInfo, Port, Options) ->
486
case CbModule:listen(Port, listen_options(Options)) of
487
{ok, ListenSocket} ->
488
{SslOpts, EmOpts} = ssl_listen_options(Options),
489
{ok, #sslsocket{pid = {ListenSocket, {SslOpts, EmOpts,
490
[{cb_info, CbInfo}]}},
485
Error = {error, _} ->
496
489
old_listen(Port, Options) ->
502
495
Opts = proplists:expand([{binary, [{mode, binary}]},
503
496
{list, [{mode, list}]}], Opts0),
505
ReuseSessionFun = fun(_, _, _, _) ->
498
ReuseSessionFun = fun(_, _, _, _) -> true end,
500
AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
501
(Other, Acc) -> [Other | Acc]
509
VerifyFun = fun(ErrorList) ->
510
case lists:foldl(fun({bad_cert,unknown_ca}, Acc) ->
514
end, [], ErrorList) of
506
case lists:foldl(AcceptBadCa, [], ErrorList) of
522
{Verify, FailIfNoPeerCert, CaCertDefalut} =
512
{Verify, FailIfNoPeerCert, CaCertDefault} =
523
513
%% Handle 0, 1, 2 for backwards compatibility
524
514
case proplists:get_value(verify, Opts, verify_none) of
526
{verify_none, false, ca_cert_defalut(verify_none, Role)};
516
{verify_none, false, ca_cert_default(verify_none, Role)};
528
{verify_peer, false, ca_cert_defalut(verify_peer, Role)};
518
{verify_peer, false, ca_cert_default(verify_peer, Role)};
530
{verify_peer, true, ca_cert_defalut(verify_peer, Role)};
520
{verify_peer, true, ca_cert_default(verify_peer, Role)};
532
{verify_none, false, ca_cert_defalut(verify_none, Role)};
522
{verify_none, false, ca_cert_default(verify_none, Role)};
534
524
{verify_peer, proplists:get_value(fail_if_no_peer_cert,
536
ca_cert_defalut(verify_peer, Role)};
526
ca_cert_default(verify_peer, Role)};
538
528
throw({error, {eoptions, {verify, Value}}})
552
542
keyfile = handle_option(keyfile, Opts, CertFile),
553
543
key = handle_option(key, Opts, undefined),
554
544
password = handle_option(password, Opts, ""),
555
cacertfile = handle_option(cacertfile, Opts, CaCertDefalut),
545
cacertfile = handle_option(cacertfile, Opts, CaCertDefault),
556
546
ciphers = handle_option(ciphers, Opts, []),
557
547
%% Server side option
558
548
reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
559
549
reuse_sessions = handle_option(reuse_sessions, Opts, true),
560
550
debug = handle_option(debug, Opts, [])
562
EmulatedSockOpts = #socket_options{
563
mode = handle_option(mode, Opts, list),
564
packet = handle_option(packet, Opts, 0),
565
header = handle_option(header, Opts, 0),
566
active = handle_option(active, Opts, true)
553
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed}),
554
SslOptions = [versions, verify, verify_fun,
555
depth, certfile, keyfile,
556
key, password, cacertfile, ciphers,
557
debug, reuse_session, reuse_sessions, ssl_imp,
569
SslOREmulated = [versions, verify, verify_fun,
570
depth, certfile, keyfile,
571
key, password, cacertfile, ciphers,
572
debug, mode, packet, header, active,
573
reuse_session, reuse_sessions, ssl_imp],
575
560
SockOpts = lists:foldl(fun(Key, PropList) ->
576
proplists:delete(Key, PropList)
577
end, Opts, SslOREmulated),
561
proplists:delete(Key, PropList)
562
end, Opts, SslOptions),
579
{ok, {SSLOptions, EmulatedSockOpts, SockOpts}}.
564
{SSLsock, Emulated} = emulated_options(SockOpts),
565
{ok, #config{ssl=SSLOptions, emulated=Emulated, inet_ssl=SSLsock,
566
inet_user=SockOpts, cb=CbInfo}}.
581
568
handle_option(OptionName, Opts, Default) ->
582
569
validate_option(OptionName,
673
635
validate_versions(Ver, Versions) ->
674
636
throw({error, {eoptions, {Ver, {versions, Versions}}}}).
676
ca_cert_defalut(verify_none, _) ->
638
validate_inet_option(mode, Value)
639
when Value =/= list, Value =/= binary ->
640
throw({error, {eoptions, {mode,Value}}});
641
validate_inet_option(packet, Value)
642
when not (is_atom(Value) or is_integer(Value)) ->
643
throw({error, {eoptions, {packet,Value}}});
644
validate_inet_option(packet_size, Value)
645
when not is_integer(Value) ->
646
throw({error, {eoptions, {packet_size,Value}}});
647
validate_inet_option(header, Value)
648
when not is_integer(Value) ->
649
throw({error, {eoptions, {header,Value}}});
650
validate_inet_option(active, Value)
651
when Value =/= true, Value =/= false, Value =/= once ->
652
throw({error, {eoptions, {active,Value}}});
653
validate_inet_option(_, _) ->
656
ca_cert_default(verify_none, _) ->
678
658
%% Client may leave verification up to the user
679
ca_cert_defalut(verify_peer, client) ->
659
ca_cert_default(verify_peer, client) ->
681
661
%% Server that wants to verify_peer must have
682
662
%% some trusted certs.
683
ca_cert_defalut(verify_peer, server) ->
663
ca_cert_default(verify_peer, server) ->
686
listen_options({_, _, InetOpts}) ->
687
%% Packet, mode, active and header must be
689
internal_inet_values() ++ InetOpts.
691
ssl_listen_options({SslOpts, SocketOpts, _}) ->
692
{SslOpts, SocketOpts}.
694
connect_options({_, _, InetOpts}) ->
695
%% Packet, mode, active and header must be
697
internal_inet_values() ++ InetOpts.
699
666
emulated_options() ->
700
[mode, packet, active, header].
667
[mode, packet, active, header, packet_size].
702
669
internal_inet_values() ->
703
[{packet, 0},{header, 0},{active, false},{mode,binary}].
670
[{packet_size,0},{packet, 0},{header, 0},{active, false},{mode,binary}].
704
671
%%[{packet, ssl},{header, 0},{active, false},{mode,binary}].
706
ssl_connection_options({SslOpts, SocketOpts, _}) ->
707
{SslOpts, SocketOpts}.
673
socket_options(InetValues) ->
675
mode = proplists:get_value(mode, InetValues),
676
header = proplists:get_value(header, InetValues),
677
active = proplists:get_value(active, InetValues),
678
packet = proplists:get_value(packet, InetValues),
679
packet_size = proplists:get_value(packet_size, InetValues)
682
emulated_options(Opts) ->
683
emulated_options(Opts, internal_inet_values(), #socket_options{}).
685
emulated_options([{mode,Opt}|Opts], Inet, Emulated) ->
686
validate_inet_option(mode,Opt),
687
emulated_options(Opts, Inet, Emulated#socket_options{mode=Opt});
688
emulated_options([{header,Opt}|Opts], Inet, Emulated) ->
689
validate_inet_option(header,Opt),
690
emulated_options(Opts, Inet, Emulated#socket_options{header=Opt});
691
emulated_options([{active,Opt}|Opts], Inet, Emulated) ->
692
validate_inet_option(active,Opt),
693
emulated_options(Opts, Inet, Emulated#socket_options{active=Opt});
694
emulated_options([{packet,Opt}|Opts], Inet, Emulated) ->
695
validate_inet_option(packet,Opt),
696
emulated_options(Opts, Inet, Emulated#socket_options{packet=Opt});
697
emulated_options([{packet_size,Opt}|Opts], Inet, Emulated) ->
698
validate_inet_option(packet_size,Opt),
699
emulated_options(Opts, Inet, Emulated#socket_options{packet_size=Opt});
700
emulated_options([Opt|Opts], Inet, Emulated) ->
701
emulated_options(Opts, [Opt|Inet], Emulated);
702
emulated_options([], Inet,Emulated) ->
709
705
cipher_suites(Version, []) ->
710
706
ssl_cipher:suites(Version);
809
805
no_format(Error) ->
810
806
io_lib:format("No format string for error: \"~p\" available.", [Error]).
812
getopts(_, _, [], Acc) ->
814
getopts(Socket, Options, [mode | Rest], Acc) ->
815
Value = {mode, Options#socket_options.mode},
816
getopts(Socket, Options, Rest, [Value | Acc]);
817
getopts(Socket, Options, [packet | Rest], Acc) ->
818
Value = {packet, Options#socket_options.packet},
819
getopts(Socket, Options, Rest, [Value | Acc]);
820
getopts(Socket, Options, [header | Rest], Acc) ->
821
Value = {header, Options#socket_options.header},
822
getopts(Socket, Options, Rest, [Value | Acc]);
823
getopts(Socket, Options, [active | Rest], Acc) ->
824
Value = {active, Options#socket_options.active},
825
getopts(Socket, Options, Rest, [Value | Acc]);
826
getopts(Socket, Options, [Tag | Rest], Acc) ->
827
{ok, [Value]} = inet:getopts(Socket, Tag),
828
getopts(Socket, Options, Rest, [Value | Acc]).
830
808
%% Start old ssl port program if needed.
831
809
ensure_old_ssl_started() ->
832
810
case whereis(ssl_server) of