An SSL server and client can be built with the (abstracted)
predicate calls from the table below. The tcp_
predicates
are provided by library(socket). The predicate ssl_context/3
defines properties of the SSL connection, while ssl_negotiate/5
establishes the SSL connection based on the wire streams created
by the TCP predicates and the context.
The SSL Server | The SSL Client |
ssl_context/3 | ssl_context/3 |
tcp_socket/1 | |
tcp_accept/3 | tcp_connect/3 |
tcp_open_socket/3 | stream_pair/3 |
ssl_negotiate/5 | ssl_negotiate/5 |
The library is abstracted to communication over streams, and is not
reliant on those streams being directly attached to sockets. The tcp_
calls here are simply the most common way to use the library. Other
two-way communication channels such as (named), pipes can just as
easily be used.
client
. Otherwise,
certificate verification may fail when negotiating a
secure connection.key_file(+FileName)
option. A server must have at
least one certificate before clients can connect. A client
must have a certificate only if the server demands the client
to identify itself with a client certificate using the
peer_cert(true)
option. If a certificate is provided, it is
necessary to also provide a matching private key via the
key_file/1 option. To configure multiple certificates, use the
option certificate_key_pairs/1 instead. Alternatively, use
ssl_add_certificate_key/4 to add certificates and keys to an
existing context.password(+Text)
or
pem_password_hook(:Goal)
option.call(Goal, +SSL, -Password)
and typically unifies
Password with a string containing the password.require_crl(true)
and
provide neither of these options, verification will necessarily
failrequire_crl(true)
if you want CRLs to actually be checked by OpenSSL.system(root_certificates)
uses a list of
trusted root certificates as provided by the OS. See
system_root_certificates/1 for details.file(Filename)
: A file containing one or more PEM-encoded
certificatescertificate(Blob)
: A certificate blobsystem(root_certificates)
: A special term which refers to
the certificates trusted by the host OS.Additional verification of the peer certificate as well as accepting certificates that are not trusted by the given set can be realised using the hook cert_verify_hook(:Goal).
call(Goal, +SSL, +ProblemCertificate, +AllCertificates, +FirstCertificate, +Error)
In case the certificate was verified by one of the provided
certifications from the cacert_file
option, Error is unified
with the atom verified
. Otherwise it contains the error
string passed from OpenSSL. Access will be granted iff the
predicate succeeds. See load_certificate/2 for a description
of the certificate terms. See cert_accept_any/5 for a dummy
implementation that accepts any certificate.
prime256v1
is used by default.true
, close the raw streams if the SSL streams are closed.
Default is false
.true
(default is false
), the server sends TLS
close_notify
when closing the connection. In addition,
this mitigates truncation attacks for both client and
server role: If EOF is encountered without having received a
TLS shutdown, an exception is raised. Well-designed
protocols are self-terminating, and this attack is therefore
very rarely a concern.sslv3
, tlsv1
, tlsv1_1
, tlsv1_2
and
tlsv1_3
. This option is available with OpenSSL 1.1.0 and
later, and should be used instead of disable_ssl_methods/1.sslv3
, tlsv1
, tlsv1_1
, tlsv1_2
and
tlsv1_3
. This option is available with OpenSSL 1.1.0 and
later, and should be used instead of disable_ssl_methods/1.sslv2
, sslv3
, sslv23
,
tlsv1
, tlsv1_1
and tlsv1_2
. This option is deprecated
starting with OpenSSL 1.1.0. Use min_protocol_version/1 and
max_protocol_version/1 instead.disable_ssl_methods
above.
Using this option is discouraged. When using OpenSSL 1.1.0
or later, this option is ignored, and a version-flexible method
is used to negotiate the connection. Using version-specific
methods is deprecated in recent OpenSSL versions, and this
option will become obsolete and ignored in the future.call(Goal, +SSL0, +HostName, -SSL)
Given the current context SSL0, and the host name of the client request, the predicate computes SSL which is used as the context for negotiating the connection. The first solution is used. If the predicate fails, the default options are used, which are those of the encompassing ssl_context/3 call. In that case, if no default certificate and key are specified, the client connection is rejected.
===
call(Goal, +SSLCtx0, +ListOfClientProtocols, -SSLCtx1, -SelectedProtocol)
===
If this option is unset and the alpn_protocols/1 option is set, then the first common protocol between client & server will be selected.
cacert_file(Spec)
option and map it to the new
cacerts(+List)
option.This predicate allows dual-stack RSA and ECDSA servers (for example), and is an alternative for using the certificate_key_pairs/1 option. As of OpenSSL 1.0.2, multiple certificate types with completely independent certificate chains are supported. If a certificate of the same type is added repeatedly to a context, the result is undefined. Currently, up to 12 additional certificates of different types are admissible.
After a successful handshake and finishing the communication the
user must close SSLRead and SSLWrite, for example using
call_cleanup(close(SSLWrite), close(SSLRead))
. If the SSL
context (created with ssl_context/3 has the option
close_parent(true)
(default false
), closing SSLRead and
SSLWrite also closes the original PlainRead and PlainWrite
streams. Otherwise these must be closed explicitly by the user.
http_open(HTTPS_url, In, []), ssl_peer_certificate(In, Cert), memberchk(subject(Subject), Cert), memberchk('CN' = CommonName), Subject)
Note that the OpenSSL CA.pl
utility creates certificates that
have a human readable textual representation in front of the PEM
representation. You can use the following to skip to the
certificate if you know it is a PEM certificate:
skip_to_pem_cert(In) :- repeat, ( peek_char(In, '-') -> ! ; skip(In, 0'\n), at_end_of_stream(In), ! ).
revoked(+Serial, DateOfRevocation)
system(root_certificates)
. The list is obtained using an OS
specific process. The current implementation is as follows:
"ROOT"
certificates from the OS.system_cacert_filename
. The initial
value of this flag is operating system dependent. For
security reasons, the flag can only be set prior to using
the SSL library. For example:
:- use_module(library(ssl)). :- set_prolog_flag(system_cacert_filename, '/home/jan/ssl/ca-bundle.crt').
private_key(KeyTerm)
where KeyTerm is an rsa/8 term
representing an RSA key, or ec/3 for EC keys.public_key(KeyTerm)
where KeyTerm is an rsa/8 term
representing an RSA key, or ec/3 for EC keys.http_open('https:/...', In, [ cert_verify_hook(cert_accept_any) ])
system(root_certificates)
for TrustedCertificates.Secure ciphers must guarantee forward secrecy, and must mitigate all known critical attacks. As of 2018, using these ciphers allows you to obtain grade A on https://www.ssllabs.com. For A+, you must also enable HTTP Strict Transport Security (HSTS) by sending a suitable header field in replies.
Note that obsolete ciphers must be disabled to reliably prevent protocol downgrade attacks.
The Ciphers list is read from the setting ssl:secure_ciphers
and
can be controlled using set_setting/2 and other predicates from
library(settings).
BEWARE: This list must be changed when attacks on these ciphers become known! Keep an eye on this setting and adapt it as necessary in the future.