ADDED: Encrypted client connections in library(sockets) via new option tls/1.
Use tls(true) to negotiate an encrypted network connection via TLS.
This commit is contained in:
@@ -42,3 +42,4 @@ ripemd160 = "0.8.0"
|
|||||||
sha3 = "0.8.2"
|
sha3 = "0.8.2"
|
||||||
blake2 = "0.8.1"
|
blake2 = "0.8.1"
|
||||||
openssl = { version = "0.10.29", features = ["vendored"] }
|
openssl = { version = "0.10.29", features = ["vendored"] }
|
||||||
|
native-tls = "0.2.4"
|
||||||
|
|||||||
@@ -409,6 +409,8 @@ The modules that ship with Scryer Prolog are also called
|
|||||||
Probabilistic predicates and random number generators.
|
Probabilistic predicates and random number generators.
|
||||||
* [`sockets`](src/prolog/lib/sockets.pl)
|
* [`sockets`](src/prolog/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.
|
||||||
* [`crypto`](src/prolog/lib/crypto.pl)
|
* [`crypto`](src/prolog/lib/crypto.pl)
|
||||||
Cryptographically secure random numbers and hashes, HMAC-based
|
Cryptographically secure random numbers and hashes, HMAC-based
|
||||||
key derivation (HKDF), password-based key derivation (PBKDF2),
|
key derivation (HKDF), password-based key derivation (PBKDF2),
|
||||||
|
|||||||
@@ -635,7 +635,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", 7) => Some(SystemClauseType::SocketClientOpen),
|
("$socket_client_open", 8) => 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),
|
||||||
|
|||||||
@@ -6,7 +6,16 @@
|
|||||||
current_hostname/1]).
|
current_hostname/1]).
|
||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
|
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, parse_socket_options_, DefaultOptions, OptionValues, Stub).
|
||||||
|
|
||||||
socket_client_open(Addr, Stream, Options) :-
|
socket_client_open(Addr, Stream, Options) :-
|
||||||
( var(Addr) ->
|
( var(Addr) ->
|
||||||
@@ -23,10 +32,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))
|
||||||
),
|
),
|
||||||
builtins:parse_stream_options(Options,
|
parse_socket_options(Options,
|
||||||
[Alias, EOFAction, Reposition, Type],
|
[Alias, EOFAction, Reposition, TLS, Type],
|
||||||
socket_client_open/3),
|
socket_client_open/3),
|
||||||
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type).
|
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type, TLS).
|
||||||
|
|
||||||
|
|
||||||
socket_server_open(Addr, ServerSocket) :-
|
socket_server_open(Addr, ServerSocket) :-
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ use std::net::{Shutdown, TcpStream};
|
|||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use native_tls::TlsStream;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum StreamType {
|
pub enum StreamType {
|
||||||
Binary,
|
Binary,
|
||||||
@@ -101,6 +103,7 @@ pub enum StreamInstance {
|
|||||||
ReadlineStream(ReadlineStream),
|
ReadlineStream(ReadlineStream),
|
||||||
Stdout,
|
Stdout,
|
||||||
TcpStream(ClauseName, TcpStream),
|
TcpStream(ClauseName, TcpStream),
|
||||||
|
TlsStream(ClauseName, TlsStream<TcpStream>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for StreamInstance {
|
impl Drop for StreamInstance {
|
||||||
@@ -109,6 +112,9 @@ impl Drop for StreamInstance {
|
|||||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||||
discard_result!(tcp_stream.shutdown(Shutdown::Both));
|
discard_result!(tcp_stream.shutdown(Shutdown::Both));
|
||||||
}
|
}
|
||||||
|
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||||
|
discard_result!(tls_stream.shutdown());
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,6 +137,8 @@ impl fmt::Debug for StreamInstance {
|
|||||||
&StreamInstance::Stdout => write!(fmt, "Stdout"),
|
&StreamInstance::Stdout => write!(fmt, "Stdout"),
|
||||||
&StreamInstance::TcpStream(_, ref tcp_stream) =>
|
&StreamInstance::TcpStream(_, ref tcp_stream) =>
|
||||||
write!(fmt, "TcpStream({:?})", tcp_stream),
|
write!(fmt, "TcpStream({:?})", tcp_stream),
|
||||||
|
&StreamInstance::TlsStream(_, ref tls_stream) =>
|
||||||
|
write!(fmt, "TlsStream({:?})", tls_stream),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,7 +418,8 @@ impl Stream {
|
|||||||
StreamInstance::InputFile(..) => {
|
StreamInstance::InputFile(..) => {
|
||||||
"read"
|
"read"
|
||||||
}
|
}
|
||||||
StreamInstance::TcpStream(..) => {
|
StreamInstance::TcpStream(..) |
|
||||||
|
StreamInstance::TlsStream(..) => {
|
||||||
"read_append"
|
"read_append"
|
||||||
}
|
}
|
||||||
StreamInstance::OutputFile(_, _, true) => {
|
StreamInstance::OutputFile(_, _, true) => {
|
||||||
@@ -449,6 +458,12 @@ impl Stream {
|
|||||||
Stream::from_inst(StreamInstance::TcpStream(address, tcp_stream))
|
Stream::from_inst(StreamInstance::TcpStream(address, tcp_stream))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn from_tls_stream(address: ClauseName, tls_stream: TlsStream<TcpStream>) -> Self {
|
||||||
|
Stream::from_inst(StreamInstance::TlsStream(address, tls_stream))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn from_file_as_output(name: ClauseName, file: File, in_append_mode: bool) -> Self {
|
fn from_file_as_output(name: ClauseName, file: File, in_append_mode: bool) -> Self {
|
||||||
@@ -510,6 +525,7 @@ impl Stream {
|
|||||||
match self.stream_inst.0.borrow().1 {
|
match self.stream_inst.0.borrow().1 {
|
||||||
// StreamInstance::Stdin |
|
// StreamInstance::Stdin |
|
||||||
StreamInstance::TcpStream(..) |
|
StreamInstance::TcpStream(..) |
|
||||||
|
StreamInstance::TlsStream(..) |
|
||||||
StreamInstance::Bytes(_) |
|
StreamInstance::Bytes(_) |
|
||||||
StreamInstance::ReadlineStream(_) |
|
StreamInstance::ReadlineStream(_) |
|
||||||
StreamInstance::DynReadSource(_) |
|
StreamInstance::DynReadSource(_) |
|
||||||
@@ -528,6 +544,7 @@ impl Stream {
|
|||||||
match self.stream_inst.0.borrow().1 {
|
match self.stream_inst.0.borrow().1 {
|
||||||
StreamInstance::Stdout
|
StreamInstance::Stdout
|
||||||
| StreamInstance::TcpStream(..)
|
| StreamInstance::TcpStream(..)
|
||||||
|
| StreamInstance::TlsStream(..)
|
||||||
| StreamInstance::Bytes(_)
|
| StreamInstance::Bytes(_)
|
||||||
| StreamInstance::OutputFile(..) => {
|
| StreamInstance::OutputFile(..) => {
|
||||||
true
|
true
|
||||||
@@ -1036,6 +1053,9 @@ impl Read for Stream {
|
|||||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||||
tcp_stream.read(buf)
|
tcp_stream.read(buf)
|
||||||
}
|
}
|
||||||
|
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||||
|
tls_stream.read(buf)
|
||||||
|
}
|
||||||
StreamInstance::ReadlineStream(ref mut rl_stream) => {
|
StreamInstance::ReadlineStream(ref mut rl_stream) => {
|
||||||
rl_stream.read(buf)
|
rl_stream.read(buf)
|
||||||
}
|
}
|
||||||
@@ -1069,6 +1089,9 @@ impl Write for Stream {
|
|||||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||||
tcp_stream.write(buf)
|
tcp_stream.write(buf)
|
||||||
}
|
}
|
||||||
|
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||||
|
tls_stream.write(buf)
|
||||||
|
}
|
||||||
StreamInstance::Bytes(ref mut cursor) => {
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
cursor.write(buf)
|
cursor.write(buf)
|
||||||
}
|
}
|
||||||
@@ -1093,6 +1116,9 @@ impl Write for Stream {
|
|||||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||||
tcp_stream.flush()
|
tcp_stream.flush()
|
||||||
}
|
}
|
||||||
|
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||||
|
tls_stream.flush()
|
||||||
|
}
|
||||||
StreamInstance::Bytes(ref mut cursor) => {
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
cursor.flush()
|
cursor.flush()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ use openssl::ec::{EcGroup, EcPoint};
|
|||||||
use openssl::bn::{BigNum, BigNumContext};
|
use openssl::bn::{BigNum, BigNumContext};
|
||||||
use openssl::nid::Nid;
|
use openssl::nid::Nid;
|
||||||
|
|
||||||
|
use native_tls::TlsConnector;
|
||||||
|
|
||||||
pub fn get_key() -> KeyEvent {
|
pub fn get_key() -> KeyEvent {
|
||||||
let key;
|
let key;
|
||||||
enable_raw_mode().expect("failed to enable raw mode");
|
enable_raw_mode().expect("failed to enable raw mode");
|
||||||
@@ -4517,7 +4519,30 @@ impl MachineState {
|
|||||||
Ok(tcp_stream) => {
|
Ok(tcp_stream) => {
|
||||||
let socket_addr = clause_name!(socket_addr, indices.atom_tbl.clone());
|
let socket_addr = clause_name!(socket_addr, indices.atom_tbl.clone());
|
||||||
|
|
||||||
let mut stream = Stream::from_tcp_stream(socket_addr, tcp_stream);
|
|
||||||
|
let mut stream =
|
||||||
|
{ let tls = match self.store(self.deref(self[temp_v!(8)])) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
||||||
|
atom.as_str()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match tls {
|
||||||
|
"false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) }
|
||||||
|
"true" => { let connector = TlsConnector::new().unwrap();
|
||||||
|
let stream = connector.connect(socket_atom.as_str(), tcp_stream).unwrap();
|
||||||
|
|
||||||
|
Stream::from_tls_stream(socket_addr, stream)
|
||||||
|
}
|
||||||
|
_ => { unreachable!() }
|
||||||
|
}
|
||||||
|
};
|
||||||
stream.options = options;
|
stream.options = options;
|
||||||
|
|
||||||
if let Some(ref alias) = &stream.options.alias {
|
if let Some(ref alias) = &stream.options.alias {
|
||||||
|
|||||||
Reference in New Issue
Block a user