MODIFIED: Remove TLS-related predicates from library(sockets).
They will become available in a new library, library(tls).
This commit is contained in:
@@ -537,10 +537,6 @@ The modules that ship with Scryer Prolog are also called
|
|||||||
is often used together with [`library(sgml)`](src/lib/sgml.pl).
|
is often used together with [`library(sgml)`](src/lib/sgml.pl).
|
||||||
* [`sockets`](src/lib/sockets.pl)
|
* [`sockets`](src/lib/sockets.pl)
|
||||||
Predicates for opening and accepting TCP connections as streams.
|
Predicates for opening and accepting TCP connections as streams.
|
||||||
TLS negotiation is performed via the option `tls(true)` in
|
|
||||||
`socket_client_open/3`, yielding secure encrypted connections.
|
|
||||||
TLS *servers* can be created with `tls_server_context/2` and
|
|
||||||
`tls_server_negotiate/3`.
|
|
||||||
* [`os`](src/lib/os.pl)
|
* [`os`](src/lib/os.pl)
|
||||||
Predicates for reasoning about environment variables.
|
Predicates for reasoning about environment variables.
|
||||||
* [`iso_ext`](src/lib/iso_ext.pl)
|
* [`iso_ext`](src/lib/iso_ext.pl)
|
||||||
|
|||||||
@@ -742,7 +742,7 @@ impl SystemClauseType {
|
|||||||
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
|
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
|
||||||
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
||||||
("$sleep", 1) => Some(SystemClauseType::Sleep),
|
("$sleep", 1) => Some(SystemClauseType::Sleep),
|
||||||
("$socket_client_open", 8) => Some(SystemClauseType::SocketClientOpen),
|
("$socket_client_open", 7) => Some(SystemClauseType::SocketClientOpen),
|
||||||
("$socket_server_open", 3) => Some(SystemClauseType::SocketServerOpen),
|
("$socket_server_open", 3) => Some(SystemClauseType::SocketServerOpen),
|
||||||
("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept),
|
("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept),
|
||||||
("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose),
|
("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose),
|
||||||
|
|||||||
@@ -3,24 +3,9 @@
|
|||||||
socket_server_open/2,
|
socket_server_open/2,
|
||||||
socket_server_accept/4,
|
socket_server_accept/4,
|
||||||
socket_server_close/1,
|
socket_server_close/1,
|
||||||
tls_server_context/2, % tls_server_context(-Context, +Options)
|
|
||||||
tls_server_negotiate/3, % tls_server_negotiate(+Context, +Stream0, -Stream)
|
|
||||||
current_hostname/1]).
|
current_hostname/1]).
|
||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
:- use_module(library(lists)).
|
|
||||||
|
|
||||||
% a client can negotiate a TLS connection by specifying the option
|
|
||||||
% tls(true) in socket_client_open/3
|
|
||||||
|
|
||||||
parse_socket_options_(tls(TLS), tls-TLS) :-
|
|
||||||
must_be(boolean, TLS), !.
|
|
||||||
parse_socket_options_(Option, OptionPair) :-
|
|
||||||
builtins:parse_stream_options_(Option, OptionPair).
|
|
||||||
|
|
||||||
parse_socket_options(Options, OptionValues, Stub) :-
|
|
||||||
DefaultOptions = [alias-[], eof_action-eof_code, reposition-false, tls-false, type-text],
|
|
||||||
builtins:parse_options_list(Options, sockets:parse_socket_options_, DefaultOptions, OptionValues, Stub).
|
|
||||||
|
|
||||||
socket_client_open(Addr, Stream, Options) :-
|
socket_client_open(Addr, Stream, Options) :-
|
||||||
( var(Addr) ->
|
( var(Addr) ->
|
||||||
@@ -37,10 +22,10 @@ socket_client_open(Addr, Stream, Options) :-
|
|||||||
;
|
;
|
||||||
throw(error(type_error(socket_address, Addr), socket_client_open/3))
|
throw(error(type_error(socket_address, Addr), socket_client_open/3))
|
||||||
),
|
),
|
||||||
parse_socket_options(Options,
|
builtins:parse_stream_options(Options,
|
||||||
[Alias, EOFAction, Reposition, TLS, Type],
|
[Alias, EOFAction, Reposition, Type],
|
||||||
socket_client_open/3),
|
socket_client_open/3),
|
||||||
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type, TLS).
|
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type).
|
||||||
|
|
||||||
|
|
||||||
socket_server_open(Addr, ServerSocket) :-
|
socket_server_open(Addr, ServerSocket) :-
|
||||||
@@ -70,65 +55,3 @@ socket_server_close(ServerSocket) :-
|
|||||||
|
|
||||||
current_hostname(HostName) :-
|
current_hostname(HostName) :-
|
||||||
'$current_hostname'(HostName).
|
'$current_hostname'(HostName).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
TLS Servers
|
|
||||||
===========
|
|
||||||
|
|
||||||
Use tls_server_context/2 to create a TLS context, for example with:
|
|
||||||
|
|
||||||
tls_server_context(Context, [pkcs12(Chars)])
|
|
||||||
|
|
||||||
where Chars is a list of characters with the contents of a
|
|
||||||
DER-formatted PKCS #12 archive. The option password(Ps) can be used
|
|
||||||
to specify the password Ps (also a string) for decrypting the key.
|
|
||||||
On some versions of OSX, and potentially also on other platforms,
|
|
||||||
empty passwords are not supported.
|
|
||||||
|
|
||||||
The archive should contain a leaf certificate and its private key,
|
|
||||||
as well any intermediate certificates that should be sent to
|
|
||||||
clients to allow them to build a chain to a trusted root. The chain
|
|
||||||
certificates should be in order from the leaf certificate towards
|
|
||||||
the root.
|
|
||||||
|
|
||||||
PKCS #12 archives typically have the file extension .p12 or .pfx,
|
|
||||||
and can be created with the OpenSSL pkcs12 tool:
|
|
||||||
|
|
||||||
$ openssl pkcs12 -export -out identity.pfx \
|
|
||||||
-inkey key.pem -in cert.pem -certfile chain_certs.pem
|
|
||||||
|
|
||||||
|
|
||||||
You can use phrase_from_file/3 from library(pio) and seq//1 from
|
|
||||||
library(dcgs) to read the contents of "identity.pfx" into a string:
|
|
||||||
|
|
||||||
phrase_from_file(seq(Chars), "identity.pfx", [type(binary)])
|
|
||||||
|
|
||||||
The obtained context should be treated as an opaque Prolog term.
|
|
||||||
|
|
||||||
Using the context and an existing stream S0 (for example, the
|
|
||||||
result of socket_server_accept/4), a TLS stream S can be negotiated
|
|
||||||
by a Prolog-based server with:
|
|
||||||
|
|
||||||
tls_server_negotiate(Context, S0, S)
|
|
||||||
|
|
||||||
S will be an encrypted and authenticated stream with the client.
|
|
||||||
|
|
||||||
The advantage of separating the creation of the server context from
|
|
||||||
negotiating a connection is that the context can be created only
|
|
||||||
once, and quickly cloned for every incoming connection. This is
|
|
||||||
currently not implemented: In the present implementation, a new context
|
|
||||||
is created for every connection, using the specified parameters.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
tls_server_context(tls_context(Cert,Password), Options) :-
|
|
||||||
( member(pcks12(Cert), Options) ->
|
|
||||||
must_be(chars, Cert)
|
|
||||||
; domain_error(contains_pcks12, Options, tls_server_context/2)
|
|
||||||
),
|
|
||||||
( member(password(Password), Options) ->
|
|
||||||
must_be(chars, Password)
|
|
||||||
; Password = ""
|
|
||||||
).
|
|
||||||
|
|
||||||
tls_server_negotiate(tls_context(Cert,Password), S0, S) :-
|
|
||||||
'$tls_accept_client'(Cert, Password, S0, S).
|
|
||||||
|
|||||||
Reference in New Issue
Block a user