ssl
Interface Functions for Secure Socket Layer
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()} |
{verify_fun, {fun(), term()}} |
{fail_if_no_peer_cert, boolean()}
{depth, integer()} |
{cert, der_bin()}| {certfile, path()} |
{key, der_bin()} | {keyfile, path()} | {password, string()} |
{cacerts, [der_bin()]} | {cacertfile, path()} |
|{dh, der_bin()} | {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.
der_bin() = binary() -Asn1 DER encoded entity as an erlang binary.
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 - COMMON for SERVER and CLIENT
Options described here are options that are have the same meaning in the client and the server.
- {cert, der_bin()}
- The DER encoded users certificate. If this option is supplied it will override the certfile option.
- {certfile, path()}
- Path to a file containing the user's certificate.
- {key, der_bin()}
- The DER encoded users private key. If this option is supplied it will override the keyfile option.
- {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.
- {cacerts, [der_bin()]}
- The DER encoded trusted certificates. If this option is supplied it will override the cacertfile option.
- {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.
- {ciphers, ciphers()}
- The cipher suites that should be supported. 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. Defaults to new.
- {secure_renegotiate, boolean()}
- Specifies if to reject renegotiation attempt that does not live up to RFC 5746. By default secure_renegotiate is set to false i.e. secure renegotiation will be used if possible but it will fallback to unsecure renegotiation if the peer does not support RFC 5746.
- {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.
- {verify_fun, {Verifyfun :: fun(), InitialUserState :: term()}}
-
The verification fun should be defined as:
fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} | {extension, #'Extension'{}}, InitialUserState :: term()) -> {valid, UserState :: term()} | {fail, Reason :: term()} | {unknown, UserState :: term()}.
The verify fun will be called during the X509-path validation when an error or an extension unknown to the ssl application is encountered. Additionally it will be called when a certificate is considered valid by the path validation to allow access to each certificate in the path to the user application. See public_key(3) for definition of #'OtpCertificate'{} and #'Extension'{}.
If the verify callback fun returns {fail, Reason}, the verification process is immediately stopped and an alert is sent to the peer and the TLS/SSL handshake is terminated. If the verify callback fun returns {valid, UserState}, the verification process is continued. If the verify callback fun always returns {valid, UserState}, the TLS/SSL handshake will not be terminated with respect to verification failures and the connection will be established. If called with an extension unknown to the user application the return value {unknown, UserState} should be used.
The default verify_fun option in verify_peer mode:
{fun(_,{bad_cert, _} = Reason, _) -> {fail, Reason}; (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> {valid, UserState} end, []}
The default verify_fun option in verify_none mode:
{fun(_,{bad_cert, unknown_ca}, UserState) -> {valid, UserState}; (_,{bad_cert, _} = Reason, _) -> {fail, Reason}; (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> {valid, UserState} end, []}
Possible path validation errors:
{bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, unknown_ca}, {bad_cert, name_not_permitted}, {bad_cert, missing_basic_constraint}, {bad_cert, invalid_key_usage}
SSL OPTION DESCRIPTIONS - CLIENT SIDE
Option described here are client specific or has a slightly different meaning in the client than in the server.
- {verify, verify_type()}
- In verify_none mode the x509-path validation error {bad_cert, unknown_ca} will automatically be accepted. See also the verify_fun option.
- {reuse_sessions, boolean()}
- Specifies if client should try to reuse sessions when possible.
SSL OPTION DESCRIPTIONS - SERVER SIDE
Option described here are server specific or has a slightly different meaning in the server than in the client.
- {dh, der_bin()}
- The DER encoded Diffie Hellman parameters. If this option is supplied it will override the dhfile option.
- {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 default parameters will be used.
- {verify, verify_type()}
- Servers only do the x509-path validation in verify_peer mode, 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, i.e. 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).
- {reuse_sessions, boolean()}
- Specifies if the server should agree to reuse sessions when the clients request to do so. See also the reuse_session option.
- {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
.
Functions
cipher_suites() ->
cipher_suites(Type) -> ciphers()
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}
Socket = socket()
SslOptions = [ssloption()]
Timeout = integer() | infinity
SslSocket = sslsocket()
Reason = term()
Upgrades a gen_tcp, or equivalent, connected socket to a ssl socket i.e. performs the client-side ssl handshake.
connect(Host, Port, Options) ->
connect(Host, Port, Options, Timeout) -> {ok, SslSocket} | {error, Reason}
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}
SslSocket = sslsocket()
Reason = term()
Close a ssl connection.
controlling_process(SslSocket, NewOwner) -> ok | {error, Reason}
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}
CipherSuite = ciphersuite()
ProtocolVersion = protocol()
Returns the negotiated protocol version and cipher suite.
format_error(Reason) -> string()
Reason = term()
Presents the error returned by an ssl function as a printable string.
getopts(Socket) ->
getopts(Socket, OptionNames) -> {ok, [socketoption()]} | {error, Reason}
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}
Port = integer()
Options = options()
ListenSocket = sslsocket()
Creates a ssl listen socket.
peercert(Socket) -> {ok, Cert} | {error, Reason}
Socket = sslsocket()
Cert = binary()
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}
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}
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}
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}
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}
Socket = sslsocket()
Options = [socketoption]()
Sets options according to Options
for the socket
Socket
.
shutdown(Socket, How) -> ok | {error, Reason}
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}
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}
ListenSocket = socket()
SslOptions = ssloptions()
Timeout = integer()
Reason = term()
Upgrades a gen_tcp, or equivalent, socket to a ssl socket i.e. performs the ssl server-side handshake.
Warning!
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}
Socket = sslsocket()
Address = ipaddress()
Port = integer()
Returns the local address and port number of the socket
Socket
.
start() ->
start(Type) -> ok | {error, Reason}
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}
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}]
SslAppVer = string()
SupportedSslVer = [protocol()]
AvailableSslVsn = [protocol()]
Returns version information relevant for the ssl application.
SEE ALSO
inet(3) and gen_tcp(3)
- cipher_suites/0
- cipher_suites/1
- connect/2
- connect/3
- connect/3-1
- connect/4
- close/1
- controlling_process/2
- connection_info/1
- format_error/1
- getopts/1
- getopts/2
- listen/2
- peercert/1
- peername/1
- recv/2
- recv/3
- renegotiate/1
- send/2
- setopts/2
- shutdown/2
- ssl_accept/1
- ssl_accept/2
- ssl_accept/2-1
- ssl_accept/3
- sockname/1
- start/0
- start/1
- stop/0
- transport_accept/1
- transport_accept/2
- versions/0