Using the SSL application

## 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 directory `ssl-X.Y.Z/examples`, with source code in `src` and the compiled module in `ebin` 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 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:

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 the `ssl: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"])}].

Copyright © 1991-2007 Ericsson AB