diff options
author | Erlang/OTP <[email protected]> | 2010-02-12 10:29:45 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2010-02-12 10:29:45 +0000 |
commit | 96ceb366d9f600e645516f24396c976fb738182a (patch) | |
tree | 65517b7865a8edb136c9ef7b90e120d1389cfd37 /lib/ssl/src | |
parent | 9e009689743b32168ec0b5be8cb113d5867fec3f (diff) | |
parent | 464f2bac3b5dadd35add52fdee2ccfe8e05facd9 (diff) | |
download | otp-96ceb366d9f600e645516f24396c976fb738182a.tar.gz otp-96ceb366d9f600e645516f24396c976fb738182a.tar.bz2 otp-96ceb366d9f600e645516f24396c976fb738182a.zip |
Merge branch 'yh/packet_option_for_new_ssl_send' into ccase/r13b04_dev
* yh/packet_option_for_new_ssl_send:
Fixed ssl:setopts(Socket, binary) which was didn't work for 'new' ssl.
Fixed bug file cache bug and improved the error messages.
Allow <c>ssl:listen/2</c> to be called with option {ssl_imp, old}.
prepend packet size bytes in ssl:send() in new_ssl implementation
OTP-8441 ssl:send/2 ignored packet option, fix provided by YAMASHINA Hio.
Fixed a file cache bug which caused problems when the same file
was used for both cert and cacert.
Allow ssl:listen/2 to be called with option {ssl_imp, old}.
Fixed ssl:setopts(Socket, binary) which didn't work for 'new'
ssl..
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/ssl.erl | 19 | ||||
-rw-r--r-- | lib/ssl/src/ssl_broker.erl | 16 | ||||
-rw-r--r-- | lib/ssl/src/ssl_certificate_db.erl | 51 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 74 | ||||
-rw-r--r-- | lib/ssl/src/ssl_manager.erl | 37 |
5 files changed, 122 insertions, 75 deletions
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 1222fe97fd..de74c91505 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -129,7 +129,8 @@ listen(Port, Options0) -> %% so that new and old ssl can be run by the same %% code, however the option will be ignored by old ssl %% that hardcodes reuseaddr to true in its portprogram. - Options = proplists:delete(reuseaddr, Options0), + Options1 = proplists:delete(reuseaddr, Options0), + Options = proplists:delete(ssl_imp, Options1), old_listen(Port, Options); Value -> {error, {eoptions, {ssl_imp, Value}}} @@ -366,8 +367,10 @@ getopts(#sslsocket{} = Socket, Options) -> %% %% Description: %%-------------------------------------------------------------------- -setopts(#sslsocket{fd = new_ssl, pid = Pid}, Options) when is_pid(Pid) -> - ssl_connection:set_opts(Pid, Options); +setopts(#sslsocket{fd = new_ssl, pid = Pid}, Opts0) when is_pid(Pid) -> + Opts = proplists:expand([{binary, [{mode, binary}]}, + {list, [{mode, list}]}], Opts0), + ssl_connection:set_opts(Pid, Opts); setopts(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}, OptTags) -> inet:setopts(ListenSocket, OptTags); setopts(#sslsocket{} = Socket, Options) -> diff --git a/lib/ssl/src/ssl_broker.erl b/lib/ssl/src/ssl_broker.erl index 178fb5fcb9..7ef88baf2b 100644 --- a/lib/ssl/src/ssl_broker.erl +++ b/lib/ssl/src/ssl_broker.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -333,9 +333,9 @@ init([Client, Type]) -> debug1(Debug, Type, "in start, client = ~w", [Client]), {ok, #st{brokertype = Type, server = Server, client = Client, collector = Client, debug = Debug}}; - true -> - {stop, no_ssl_server} - end. + true -> + {stop, no_ssl_server} + end. %% diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl index decc6c9fea..adae92530a 100644 --- a/lib/ssl/src/ssl_certificate_db.erl +++ b/lib/ssl/src/ssl_certificate_db.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -27,7 +27,7 @@ -export([create/0, remove/1, add_trusted_certs/3, remove_trusted_certs/2, lookup_trusted_cert/3, issuer_candidate/1, - cache_pem_file/3]). + lookup_cached_certs/1, cache_pem_file/3]). %%==================================================================== %% Internal application API @@ -74,6 +74,9 @@ lookup_trusted_cert(Ref, SerialNumber, Issuer) -> {ok, Certs} end. +lookup_cached_certs(File) -> + ets:lookup(certificate_db_name(), {file, File}). + %%-------------------------------------------------------------------- %% Function: add_trusted_certs(Pid, File, Db) -> {ok, Ref} %% Pid = pid() @@ -90,7 +93,7 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) -> undefined -> NewRef = make_ref(), add_certs_from_file(File, NewRef, CertsDb), - insert(File, NewRef, 1, FileToRefDb), + insert(File, NewRef, 1, FileToRefDb), NewRef; [OldRef] -> ref_count(File,FileToRefDb,1), @@ -104,14 +107,11 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) -> %% %% Description: Cache file as binary in DB %%-------------------------------------------------------------------- -cache_pem_file(Pid, File, [_CertsDb, FileToRefDb, PidToFileDb]) -> - try ref_count(File, FileToRefDb,1) - catch _:_ -> - {ok, Content} = public_key:pem_to_der(File), - insert(File,Content,1,FileToRefDb) - end, +cache_pem_file(Pid, File, [CertsDb, _FileToRefDb, PidToFileDb]) -> + Res = {ok, Content} = public_key:pem_to_der(File), + insert({file, File}, Content, CertsDb), insert(Pid, File, PidToFileDb), - {ok, FileToRefDb}. + Res. %%-------------------------------------------------------------------- %% Function: remove_trusted_certs(Pid, Db) -> _ @@ -123,15 +123,16 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) -> Files = lookup(Pid, PidToFileDb), delete(Pid, PidToFileDb), Clear = fun(File) -> - case ref_count(File, FileToRefDb, -1) of - 0 -> - case lookup(File, FileToRefDb) of - [Ref] when is_reference(Ref) -> - remove_certs(Ref, CertsDb); - _ -> ok - end, - delete(File, FileToRefDb); - _ -> + delete({file,File}, CertsDb), + try + 0 = ref_count(File, FileToRefDb, -1), + case lookup(File, FileToRefDb) of + [Ref] when is_reference(Ref) -> + remove_certs(Ref, CertsDb); + _ -> ok + end, + delete(File, FileToRefDb) + catch _:_ -> ok end end, @@ -168,6 +169,8 @@ issuer_candidate(PrevCandidateKey) -> case ets:next(Db, PrevCandidateKey) of '$end_of_table' -> no_more_candidates; + {file, _} = Key -> + issuer_candidate(Key); Key -> [Cert] = lookup(Key, Db), {Key, Cert} @@ -189,7 +192,7 @@ ref_count(Key, Db,N) -> ets:update_counter(Db,Key,N). delete(Key, Db) -> - true = ets:delete(Db, Key). + _ = ets:delete(Db, Key). lookup(Key, Db) -> case ets:lookup(Db, Key) of diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index d9377fe3d6..bbffa1e564 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -610,7 +610,7 @@ connection(hello, State = #state{host = Host, port = Port, %% gen_fsm:sync_send_event/2,3, the instance of this function with the same %% name as the current state name StateName is called to handle the event. %%-------------------------------------------------------------------- -connection({application_data, Data}, _From, +connection({application_data, Data0}, _From, State = #state{socket = Socket, negotiated_version = Version, transport_cb = Transport, @@ -618,10 +618,16 @@ connection({application_data, Data}, _From, %% We should look into having a worker process to do this to %% parallize send and receive decoding and not block the receiver %% if sending is overloading the socket. - {Msgs, ConnectionStates1} = encode_data(Data, Version, ConnectionStates0), - Result = Transport:send(Socket, Msgs), - {reply, Result, - connection, State#state{connection_states = ConnectionStates1}}. + try + Data = encode_packet(Data0, State#state.socket_options), + {Msgs, ConnectionStates1} = encode_data(Data, Version, ConnectionStates0), + Result = Transport:send(Socket, Msgs), + {reply, Result, + connection, State#state{connection_states = ConnectionStates1}} + + catch throw:Error -> + {reply, Error, connection, State} + end. %%-------------------------------------------------------------------- %% Function: @@ -972,8 +978,14 @@ init_certificates(#ssl_options{cacertfile = CACertFile, case ssl_manager:connection_init(CACertFile, Role) of {ok, CertDbRef, CacheRef} -> init_certificates(CertDbRef, CacheRef, CertFile, Role); + {error, {badmatch, _Error}} -> + Report = io_lib:format("SSL: Error ~p Initializing: ~p ~n", + [_Error, CACertFile]), + error_logger:error_report(Report), + throw(ecacertfile); {error, _Error} -> - Report = io_lib:format("SSL: Error ~p ~n",[_Error]), + Report = io_lib:format("SSL: Error ~p Initializing: ~p ~n", + [_Error, CACertFile]), error_logger:error_report(Report), throw(ecacertfile) end. @@ -990,12 +1002,18 @@ init_certificates(CertDbRef, CacheRef, CertFile, server) -> try [OwnCert] = ssl_certificate:file_to_certificats(CertFile), {ok, CertDbRef, CacheRef, OwnCert} - catch _E:_R -> - Report = io_lib:format("SSL: ~p: ~p:~p ~p~n", - [?LINE, _E,_R, erlang:get_stacktrace()]), - error_logger:error_report(Report), - throw(ecertfile) - end. + catch + _E:{badmatch, _R={error,_}} -> + Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n", + [?LINE, _E,_R, CertFile, erlang:get_stacktrace()]), + error_logger:error_report(Report), + throw(ecertfile); + _E:_R -> + Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n", + [?LINE, _E,_R, CertFile, erlang:get_stacktrace()]), + error_logger:error_report(Report), + throw(ecertfile) + end. init_private_key(undefined, "", _Password, client) -> undefined; @@ -1006,9 +1024,15 @@ init_private_key(undefined, KeyFile, Password, _) -> PKey =:= rsa_private_key orelse PKey =:= dsa_private_key], {ok, Decoded} = public_key:decode_private_key(Der,Password), Decoded - catch _E:_R -> - Report = io_lib:format("SSL: ~p: ~p:~p ~p~n", - [?LINE, _E,_R, erlang:get_stacktrace()]), + catch + _E:{badmatch, _R={error,_}} -> + Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n", + [?LINE, _E,_R, KeyFile, erlang:get_stacktrace()]), + error_logger:error_report(Report), + throw(ekeyfile); + _E:_R -> + Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n", + [?LINE, _E,_R, KeyFile, erlang:get_stacktrace()]), error_logger:error_report(Report), throw(ekeyfile) end; @@ -1037,8 +1061,7 @@ send_all_state_event(FsmPid, Event) -> gen_fsm:send_all_state_event(FsmPid, Event). sync_send_all_state_event(FsmPid, Event) -> - sync_send_all_state_event(FsmPid, Event, ?DEFAULT_TIMEOUT -). + sync_send_all_state_event(FsmPid, Event, ?DEFAULT_TIMEOUT). sync_send_all_state_event(FsmPid, Event, Timeout) -> try gen_fsm:sync_send_all_state_event(FsmPid, Event, Timeout) @@ -1404,6 +1427,23 @@ encode_handshake(HandshakeRec, SigAlg, Version, ConnectionStates0, Hashes0) -> ssl_record:encode_handshake(Frag, Version, ConnectionStates0), {E, ConnectionStates1, Hashes1}. +encode_packet(Data, #socket_options{packet=Packet}) -> + case Packet of + 0 -> Data; + 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1); + 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1); + 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1); + _ -> + throw({error, {badarg, {eoptions, {packet, Packet}}}}) + end. + +encode_size_packet(Bin, Size, Max) -> + Len = byte_size(Bin), + case Len > Max of + true -> throw({error, {badarg, {packet_to_large, Len, Max}}}); + false -> <<Len:Size, Bin/binary>> + end. + encode_data(Data, Version, ConnectionStates) -> ssl_record:encode_data(Data, Version, ConnectionStates). diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 6b83c2ea46..0151426d43 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -74,13 +74,11 @@ connection_init(TrustedcertsFile, Role) -> call({connection_init, TrustedcertsFile, Role}). cache_pem_file(File) -> - case ets:lookup(ssl_file_to_ref,File) of - [{_,_,Content}] -> + case ssl_certificate_db:lookup_cached_certs(File) of + [{_,Content}] -> {ok, Content}; [] -> - {ok, Db} = call({cache_pem, File}), - [{_,_,Content}] = ets:lookup(Db,File), - {ok, Content} + call({cache_pem, File}) end. %%-------------------------------------------------------------------- @@ -170,13 +168,14 @@ handle_call({{connection_init, TrustedcertsFile, _Role}, Pid}, _From, session_cache = Cache} = State) -> erlang:monitor(process, Pid), Result = - case (catch ssl_certificate_db:add_trusted_certs(Pid, - TrustedcertsFile, - Db)) of - {ok, Ref} -> - {ok, Ref, Cache}; - Error -> - {error, Error} + try + {ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, TrustedcertsFile, Db), + {ok, Ref, Cache} + catch + _:{badmatch, Error} -> + {error, Error}; + _E:_R -> + {error, {_R,erlang:get_stacktrace()}} end, {reply, Result, State}; @@ -198,7 +197,9 @@ handle_call({{cache_pem, File},Pid}, _, State = #state{certificate_db = Db}) -> try ssl_certificate_db:cache_pem_file(Pid,File,Db) of Result -> {reply, Result, State} - catch _:Reason -> + catch _:{badmatch, Reason} -> + {reply, Reason, State}; + _:Reason -> {reply, {error, Reason}, State} end; |