Here we provide an introduction to using the Erlang/OTP SSL
application, which is accessed through the ssl
interface
module.
We also present example code in the Erlang module
client_server
, also provided in the directory
ssl-X.Y.Z/examples
, with source code in src
and the
compiled module in ebin
of that directory.
The ssl
module provides the user interface to the Erlang/OTP
SSL application. The interface functions provided are very similar
to those provided by the gen_tcp
and inet
modules.
Servers use the interface functions listen
and
accept
. The listen
function specifies a TCP port
to to listen to, and each call to the accept
function
establishes an incoming connection.
Clients use the connect
function which specifies the address
and port of a server to connect to, and a successful call establishes
such a connection.
The listen
and connect
functions have almost all
the options that the corresponding functions in gen_tcp/
have,
but there are also additional options specific to the SSL protocol.
The most important SSL specific option is the cacertfile
option which specifies a local file containing trusted CA
certificates which are and used for peer authentication. This
option is used by clients and servers in case they want to
authenticate their peers.
The certfile
option specifies a local path to a file
containing the certificate of the holder of the connection
endpoint. In case of a server endpoint this option is mandatory
since the contents of the sever certificate is needed in the
the handshake preceeding the establishment of a connection.
Similarly, the keyfile
option points to a local file
containing the private key of the holder of the endpoint. If the
certfile
option is present, this option has to be
specified as well, unless the private key is provided in the
same file as specified by the certfile
option (a
certificate and a private key can thus coexist in the same file).
The verify
option specifies how the peer should be verified:
The depth
option specifies the maximum length of the
verification certificate chain. Depth = 0 means the peer
certificate, depth = 1 the CA certificate, depth = 2 the next CA
certificate etc. If the verification process does not find a
trusted CA certificate within the maximum length, the verification
fails.
The ciphers
option specifies which ciphers to use (a
string of colon separated cipher names). To obtain a list of
available ciphers, evaluate the ssl:ciphers/0
function
(the SSL application has to be running).
Here is a simple client server example.
%%% Purpose: Example of SSL client and server using example certificates. -module(client_server). -export([start/0, start/1, init_connect/1]). start() -> start([ssl, subject]). start(CertOpts) -> %% Start ssl application application:start(ssl), %% Always seed ssl:seed("ellynatefttidppohjeh"), %% Let the current process be the server that listens and accepts %% Listen {ok, LSock} = ssl:listen(0, mk_opts(listen)), {ok, LPort} = ssl:port(LSock), io:fwrite("Listen: port = ~w.~n", [LPort]), %% Spawn the client process that connects to the server spawn(?MODULE, init_connect, [{LPort, CertOpts}]), %% Accept {ok, ASock} = ssl:accept(LSock), io:fwrite("Accept: accepted.~n"), {ok, Cert} = ssl:peercert(ASock, CertOpts), io:fwrite("Accept: peer cert:~n~p~n", [Cert]), io:fwrite("Accept: sending \"hello\".~n"), ssl:send(ASock, "hello"), {error, closed} = ssl:recv(ASock, 0), io:fwrite("Accept: detected closed.~n"), ssl:close(ASock), io:fwrite("Listen: closing and terminating.~n"), ssl:close(LSock), application:stop(ssl). %% Client connect init_connect({LPort, CertOpts}) -> {ok, Host} = inet:gethostname(), {ok, CSock} = ssl:connect(Host, LPort, mk_opts(connect)), io:fwrite("Connect: connected.~n"), {ok, Cert} = ssl:peercert(CSock, CertOpts), io:fwrite("Connect: peer cert:~n~p~n", [Cert]), {ok, Data} = ssl:recv(CSock, 0), io:fwrite("Connect: got data: ~p~n", [Data]), io:fwrite("Connect: closing and terminating.~n"), ssl:close(CSock). mk_opts(listen) -> mk_opts("server"); mk_opts(connect) -> mk_opts("client"); mk_opts(Role) -> Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]), [{active, false}, {verify, 2}, {depth, 2}, {cacertfile, filename:join([Dir, Role, "cacerts.pem"])}, {certfile, filename:join([Dir, Role, "cert.pem"])}, {keyfile, filename:join([Dir, Role, "key.pem"])}].