2 Using the SSL application
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 directoryssl-X.Y.Z/examples
, with source code insrc
and the compiled module inebin
of that directory.2.1 The ssl Module
The
ssl
module provides the user interface to the Erlang/OTP SSL application. The interface functions provided are very similar to those provided by thegen_tcp
andinet
modules.Servers use the interface functions
listen
andaccept
. Thelisten
function specifies a TCP port to to listen to, and each call to theaccept
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
andconnect
functions have almost all the options that the corresponding functions ingen_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 thecertfile
option is present, this option has to be specified as well, unless the private key is provided in the same file as specified by thecertfile
option (a certificate and a private key can thus coexist in the same file).The
verify
option specifies how the peer should be verified:
- 0
- Do not verify the peer,
- 1
- Verify peer,
- 2
- Verify peer, fail the verification if the peer has no certificate.
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 thessl:ciphers/0
function (the SSL application has to be running).2.2 A Client-Server Example
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"])}].