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"
|
||||
blake2 = "0.8.1"
|
||||
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.
|
||||
* [`sockets`](src/prolog/lib/sockets.pl)
|
||||
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)
|
||||
Cryptographically secure random numbers and hashes, HMAC-based
|
||||
key derivation (HKDF), password-based key derivation (PBKDF2),
|
||||
|
||||
@@ -635,7 +635,7 @@ impl SystemClauseType {
|
||||
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
|
||||
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
||||
("$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_accept", 7) => Some(SystemClauseType::SocketServerAccept),
|
||||
("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose),
|
||||
|
||||
@@ -6,7 +6,16 @@
|
||||
current_hostname/1]).
|
||||
|
||||
:- 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) :-
|
||||
( var(Addr) ->
|
||||
@@ -23,10 +32,10 @@ socket_client_open(Addr, Stream, Options) :-
|
||||
;
|
||||
throw(error(type_error(socket_address, Addr), socket_client_open/3))
|
||||
),
|
||||
builtins:parse_stream_options(Options,
|
||||
[Alias, EOFAction, Reposition, Type],
|
||||
socket_client_open/3),
|
||||
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type).
|
||||
parse_socket_options(Options,
|
||||
[Alias, EOFAction, Reposition, TLS, Type],
|
||||
socket_client_open/3),
|
||||
'$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type, TLS).
|
||||
|
||||
|
||||
socket_server_open(Addr, ServerSocket) :-
|
||||
|
||||
@@ -17,6 +17,8 @@ use std::net::{Shutdown, TcpStream};
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
|
||||
use native_tls::TlsStream;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum StreamType {
|
||||
Binary,
|
||||
@@ -101,6 +103,7 @@ pub enum StreamInstance {
|
||||
ReadlineStream(ReadlineStream),
|
||||
Stdout,
|
||||
TcpStream(ClauseName, TcpStream),
|
||||
TlsStream(ClauseName, TlsStream<TcpStream>)
|
||||
}
|
||||
|
||||
impl Drop for StreamInstance {
|
||||
@@ -109,6 +112,9 @@ impl Drop for StreamInstance {
|
||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||
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::TcpStream(_, ref 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(..) => {
|
||||
"read"
|
||||
}
|
||||
StreamInstance::TcpStream(..) => {
|
||||
StreamInstance::TcpStream(..) |
|
||||
StreamInstance::TlsStream(..) => {
|
||||
"read_append"
|
||||
}
|
||||
StreamInstance::OutputFile(_, _, true) => {
|
||||
@@ -449,6 +458,12 @@ impl 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]
|
||||
pub(crate)
|
||||
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 {
|
||||
// StreamInstance::Stdin |
|
||||
StreamInstance::TcpStream(..) |
|
||||
StreamInstance::TlsStream(..) |
|
||||
StreamInstance::Bytes(_) |
|
||||
StreamInstance::ReadlineStream(_) |
|
||||
StreamInstance::DynReadSource(_) |
|
||||
@@ -528,6 +544,7 @@ impl Stream {
|
||||
match self.stream_inst.0.borrow().1 {
|
||||
StreamInstance::Stdout
|
||||
| StreamInstance::TcpStream(..)
|
||||
| StreamInstance::TlsStream(..)
|
||||
| StreamInstance::Bytes(_)
|
||||
| StreamInstance::OutputFile(..) => {
|
||||
true
|
||||
@@ -1036,6 +1053,9 @@ impl Read for Stream {
|
||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||
tcp_stream.read(buf)
|
||||
}
|
||||
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||
tls_stream.read(buf)
|
||||
}
|
||||
StreamInstance::ReadlineStream(ref mut rl_stream) => {
|
||||
rl_stream.read(buf)
|
||||
}
|
||||
@@ -1069,6 +1089,9 @@ impl Write for Stream {
|
||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||
tcp_stream.write(buf)
|
||||
}
|
||||
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||
tls_stream.write(buf)
|
||||
}
|
||||
StreamInstance::Bytes(ref mut cursor) => {
|
||||
cursor.write(buf)
|
||||
}
|
||||
@@ -1093,6 +1116,9 @@ impl Write for Stream {
|
||||
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
|
||||
tcp_stream.flush()
|
||||
}
|
||||
StreamInstance::TlsStream(_, ref mut tls_stream) => {
|
||||
tls_stream.flush()
|
||||
}
|
||||
StreamInstance::Bytes(ref mut cursor) => {
|
||||
cursor.flush()
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ use openssl::ec::{EcGroup, EcPoint};
|
||||
use openssl::bn::{BigNum, BigNumContext};
|
||||
use openssl::nid::Nid;
|
||||
|
||||
use native_tls::TlsConnector;
|
||||
|
||||
pub fn get_key() -> KeyEvent {
|
||||
let key;
|
||||
enable_raw_mode().expect("failed to enable raw mode");
|
||||
@@ -4517,7 +4519,30 @@ impl MachineState {
|
||||
Ok(tcp_stream) => {
|
||||
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;
|
||||
|
||||
if let Some(ref alias) = &stream.options.alias {
|
||||
|
||||
Reference in New Issue
Block a user