aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2010-02-12 10:29:45 +0000
committerErlang/OTP <[email protected]>2010-02-12 10:29:45 +0000
commit96ceb366d9f600e645516f24396c976fb738182a (patch)
tree65517b7865a8edb136c9ef7b90e120d1389cfd37 /lib/ssl/src
parent9e009689743b32168ec0b5be8cb113d5867fec3f (diff)
parent464f2bac3b5dadd35add52fdee2ccfe8e05facd9 (diff)
downloadotp-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.erl19
-rw-r--r--lib/ssl/src/ssl_broker.erl16
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl51
-rw-r--r--lib/ssl/src/ssl_connection.erl74
-rw-r--r--lib/ssl/src/ssl_manager.erl37
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;