ssl

MODULE

ssl

MODULE SUMMARY

Interface Functions for Secure Socket Layer

DESCRIPTION

This module contains interface functions to the Secure Socket Layer.

SSL

  • ssl requires the crypto an public_key applications.
  • Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0
  • For security reasons sslv2 is not supported.
  • Ephemeral Diffie-Hellman cipher suites are supported but not Diffie Hellman Certificates cipher suites.
  • Export cipher suites are not supported as the U.S. lifted its export restrictions in early 2000.
  • CRL and policy certificate extensions are not supported yet.

COMMON DATA TYPES

The following data types are used in the functions below:

boolean() = true | false

property() = atom()

option() = socketoption() | ssloption() | transportoption()

socketoption() = [{property(), term()}] - defaults to [{mode,list},{packet, 0},{header, 0},{active, true}].

For valid options see inet(3) and gen_tcp(3) .

ssloption() = {verify, verify_type()} | {fail_if_no_peer_cert, boolean()} {depth, integer()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {dhfile, path()} | {ciphers, ciphers()} | {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()}

transportoption() = {CallbackModule, DataTag, ClosedTag} - defaults to {gen_tcp, tcp, tcp_closed}. Ssl may be run over any reliable transport protocol that has an equivalent API to gen_tcp's.

      CallbackModule = atom()

      DataTag = atom() - tag used in socket data message.

      ClosedTag = atom() - tag used in socket close message.

verify_type() = verify_none | verify_peer

path() = string() - representing a file path.

host() = hostname() | ipaddress()

hostname() = string()

ip_address() = {N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6

sslsocket() - opaque to the user.

protocol() = sslv3 | tlsv1

ciphers() = [ciphersuite()] | string() (according to old API)

ciphersuite() = {key_exchange(), cipher(), hash()}

key_exchange() = rsa | dhe_dss | dhe_rsa

cipher() = rc4_128 | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc

hash() = md5 | sha

ssl_imp() = new | old - default is new.

SSL OPTION DESCRIPTIONS

{verify, verify_type()}
If verify_none is specified x509-certificate path validation errors at the client side will not automatically cause the connection to fail, as it will if the verify type is verify_peer. See also the option verify_fun. Servers only do the path validation if verify_peer is set to true, as it then will send a certificate request to the client (this message is not sent if the verify option is verify_none) and you may then also want to specify the option fail_if_no_peer_cert.
{fail_if_no_peer_cert, boolean()}
Used together with {verify, verify_peer} by a ssl server. If set to true, the server will fail if the client does not have a certificate to send, e.i sends a empty certificate, if set to false it will only fail if the client sends a invalid certificate (an empty certificate is considered valid).
{verify_fun, fun(ErrorList) -> boolean()}
Used by the ssl client to determine if x509-certificate path validations errors are acceptable or if the connection should fail. Defaults to:
fun(ErrorList) ->
	case lists:foldl(fun({bad_cert,unknown_ca}, Acc) ->
						  Acc;
			    (Other, Acc) ->
				 [Other | Acc]
			 end, [], ErrorList) of
	    [] ->
		true;
	    [_|_] ->
		false
	end
end
I.e. by default if the only error found was that the CA-certificate holder was unknown this will be accepted. Possible errors in the error list are: {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, name_not_permitted}, {bad_cert, unknown_ca}, {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, name_not_permitted}, {bad_cert, cert_revoked} (not implemented yet), {bad_cert, unknown_critical_extension} or {bad_cert, term()} (Will be relevant later when an option is added for the user to be able to verify application specific extensions.)
{depth, integer()}
Specifies the maximum verification depth, i.e. how far in a chain of certificates the verification process can proceed before the verification is considered to fail. Peer certificate = 0, CA certificate = 1, higher level CA certificate = 2, etc. The value 2 thus means that a chain can at most contain peer cert, CA cert, next CA cert, and an additional CA cert. The default value is 1.
{certfile, path()}
Path to a file containing the user's certificate. Optional for clients but note that some servers requires that the client can certify itself.
{keyfile, path()}
Path to file containing user's private PEM encoded key. As PEM-files may contain several entries this option defaults to the same file as given by certfile option.
{password, string()}
String containing the user's password. Only used if the private keyfile is password protected.
{cacertfile, path()}
Path to file containing PEM encoded CA certificates (trusted certificates used for verifying a peer certificate). May be omitted if you do not want to verify the peer.
{dhfile, path()}
Path to file containing PEM encoded Diffie Hellman parameters, for the server to use if a cipher suite using Diffie Hellman key exchange is negotiated. If not specified hardcode parameters will be used.
{ciphers, ciphers()}
The function ciphers_suites/0 can be used to find all available ciphers.
{ssl_imp, ssl_imp()}
Specify which ssl implementation you want to use.
{reuse_sessions, boolean()}
Specifies if ssl sessions should be reused when possible.
{reuse_session, fun(SuggestedSessionId, PeerCert, Compression, CipherSuite) -> boolean()}
Enables the ssl server to have a local policy for deciding if a session should be reused or not, only meaning full if reuse_sessions is set to true. SuggestedSessionId is a binary(), PeerCert is a DER encoded certificate, Compression is an enumeration integer and CipherSuite of type ciphersuite().

General

When a ssl socket is in active mode (the default), data from the socket is delivered to the owner of the socket in the form of messages:

  • {ssl, Socket, Data}
  • {ssl_closed, Socket}
  • {ssl_error, Socket, Reason}

A Timeout argument specifies a timeout in milliseconds. The default value for a Timeout argument is infinity.

EXPORTS

cipher_suites() ->
cipher_suites(Type) -> ciphers()

Types:

Type = erlang | openssl

Returns a list of supported cipher suites. cipher_suites() is equivalent to cipher_suites(erlang). Type openssl is provided for backwards compatibility with old ssl that used openssl.

connect(Socket, SslOptions) ->
connect(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {error, Reason}

Types:

Socket = socket()
SslOptions = [ssloption()]
Timeout = integer() | infinity
SslSocket = sslsocket()
Reason = term()

Upgrades a gen_tcp, or equivalent, connected socket to a ssl socket e.i performs the client-side ssl handshake.

connect(Host, Port, Options) ->
connect(Host, Port, Options, Timeout) -> {ok, SslSocket} | {error, Reason}

Types:

Host = host()
Port = integer()
Options = [option()]
Timeout = integer() | infinity
SslSocket = sslsocket()
Reason = term()

Opens an ssl connection to Host, Port.

close(SslSocket) -> ok | {error, Reason}

Types:

SslSocket = sslsocket()
Reason = term()

Close a ssl connection.

controlling_process(SslSocket, NewOwner) -> ok | {error, Reason}

Types:

SslSocket = sslsocket()
NewOwner = pid()
Reason = term()

Assigns a new controlling process to the ssl-socket. A controlling process is the owner of a ssl-socket, and receives all messages from the socket.

connection_info(SslSocket) -> {ok, {ProtocolVersion, CipherSuite}} | {error, Reason}

Types:

CipherSuite = ciphersuite()
ProtocolVersion = protocol()

Returns the negotiated protocol version and cipher suite.

format_error(Reason) -> string()

Types:

Reason = term()

Presents the error returned by an ssl function as a printable string.

getopts(Socket) ->
getopts(Socket, OptionNames) -> {ok, [socketoption()]} | {error, Reason}

Types:

Socket = sslsocket()
OptionNames = [property()]

Get the value of the specified socket options, if no options are specified all options are returned.

listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}

Types:

Port = integer()
Options = options()
ListenSocket = sslsocket()

Creates a ssl listen socket.

peercert(Socket) -> {ok, Cert} | {error, Reason}

Types:

Socket = sslsocket()
Cert = binary()
Subject = term()

The peer certificate is returned as a DER encoded binary. The certificate can be decoded with public_key:pkix_decode_cert/2.

peername(Socket) -> {ok, {Address, Port}} | {error, Reason}

Types:

Socket = sslsocket()
Address = ipaddress()
Port = integer()

Returns the address and port number of the peer.

recv(Socket, Length) ->
recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}

Types:

Socket = sslsocket()
Length = integer()
Timeout = integer()
Data = [char()] | binary()

This function receives a packet from a socket in passive mode. A closed socket is indicated by a return value {error, closed}.

The Length argument is only meaningful when the socket is in raw mode and denotes the number of bytes to read. If Length = 0, all available bytes are returned. If Length > 0, exactly Length bytes are returned, or an error; possibly discarding less than Length bytes of data when the socket gets closed from the other side.

The optional Timeout parameter specifies a timeout in milliseconds. The default value is infinity.

renegotiate(Socket) -> ok | {error, Reason}

Types:

Socket = sslsocket()

Initiates a new handshake. A notable return value is {error, renegotiation_rejected} indicating that the peer refused to go through with the renegotiation but the connection is still active using the previously negotiated session.

send(Socket, Data) -> ok | {error, Reason}

Types:

Socket = sslsocket()
Data = iolist() | binary()

Writes Data to Socket.

A notable return value is {error, closed} indicating that the socket is closed.

setopts(Socket, Options) -> ok | {error, Reason}

Types:

Socket = sslsocket()
Options = [socketoption]()

Sets options according to Options for the socket Socket.

shutdown(Socket, How) -> ok | {error, Reason}

Types:

Socket = sslsocket()
How = read | write | read_write
Reason = reason()

Immediately close a socket in one or two directions.

How == write means closing the socket for writing, reading from it is still possible.

To be able to handle that the peer has done a shutdown on the write side, the {exit_on_close, false} option is useful.

ssl_accept(ListenSocket) ->
ssl_accept(ListenSocket, Timeout) -> ok | {error, Reason}

Types:

ListenSocket = sslsocket()
Timeout = integer()
Reason = term()

The ssl_accept function establish the SSL connection on the server side. It should be called directly after transport_accept, in the spawned server-loop.

ssl_accept(ListenSocket, SslOptions) ->
ssl_accept(ListenSocket, SslOptions, Timeout) -> {ok, Socket} | {error, Reason}

Types:

ListenSocket = socket()
SslOptions = ssloptions()
Timeout = integer()
Reason = term()

Upgrades a gen_tcp, or equivalent, socket to a ssl socket e.i performs the ssl server-side handshake.

Note

Note that the listen socket should be in {active, false} mode before telling the client that the server is ready to upgrade and calling this function, otherwise the upgrade may or may not succeed depending on timing.

sockname(Socket) -> {ok, {Address, Port}} | {error, Reason}

Types:

Socket = sslsocket()
Address = ipaddress()
Port = integer()

Returns the local address and port number of the socket Socket.

start() ->
start(Type) -> ok | {error, Reason}

Types:

Type = permanent | transient | temporary

Starts the Ssl application. Default type is temporary. application(3)

stop() -> ok

Stops the Ssl application. application(3)

transport_accept(Socket) ->
transport_accept(Socket, Timeout) -> {ok, NewSocket} | {error, Reason}

Types:

Socket = NewSocket = sslsocket()
Timeout = integer()
Reason = reason()

Accepts an incoming connection request on a listen socket. ListenSocket must be a socket returned from listen/2. The socket returned should be passed to ssl_accept to complete ssl handshaking and establishing the connection.

Warning

The socket returned can only be used with ssl_accept, no traffic can be sent or received before that call.

The accepted socket inherits the options set for ListenSocket in listen/2.

The default value for Timeout is infinity. If Timeout is specified, and no connection is accepted within the given time, {error, timeout} is returned.

versions() -> [{SslAppVer, SupportedSslVer, AvailableSslVsn}]

Types:

SslAppVer = string()
SupportedSslVer = [protocol()]
AvailableSslVsn = [protocol()]

Returns version information relevant for the ssl application.

SEE ALSO