2 Using the SSL application
Here we provide an introduction to using the Erlang/OTP SSL application, which is accessed through the
sslinterface module.We also present example code in the Erlang module
client_server, also provided in the directoryssl-X.Y.Z/examples, with source code insrcand the compiled module inebinof that directory.2.1 The ssl Module
The
sslmodule provides the user interface to the Erlang/OTP SSL application. The interface functions provided are very similar to those provided by thegen_tcpandinetmodules.Servers use the interface functions
listenandaccept. Thelistenfunction specifies a TCP port to to listen to, and each call to theacceptfunction establishes an incoming connection.Clients use the
connectfunction which specifies the address and port of a server to connect to, and a successful call establishes such a connection.The
listenandconnectfunctions 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
cacertfileoption 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
certfileoption 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
keyfileoption points to a local file containing the private key of the holder of the endpoint. If thecertfileoption is present, this option has to be specified as well, unless the private key is provided in the same file as specified by thecertfileoption (a certificate and a private key can thus coexist in the same file).The
verifyoption 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
depthoption 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
ciphersoption specifies which ciphers to use (a string of colon separated cipher names). To obtain a list of available ciphers, evaluate thessl:ciphers/0function (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"])}].